NOIP模拟2
期望得分:100+100+100=300
实际得分:70+40+20=130
T1 [SCOI2007]kshort弱化版
Description
有n个城市和m条单向道路,城市编号为1~n。每条道路连接两个不同的城市,且任意两条道路要么起点不同要么终点不同,因此n和m满足m<=n(n-1)。给定两个城市a和b,可以给a到b的所有简单路(所有城市最多经过一次,包括起点和终点)排序:先按长度从小到大排序,长度相同时按照字典序从小到大排序。你的任务是求出a到b的第k短路。
Input
输入第一行包含五个正整数n, m, k, a, b。以下m行每行三个整数u, v, l,表示从城市u到城市v有一条长度为l的单向道路。100%的数据满足:2<=n<=50, 1<=k<=200
Output
如果a到b的简单路不足k条,输出No,否则输出第k短路:从城市a开始依次输出每个到达的城市,直到城市b,中间用减号"-"分割。
基本思路:A*跑k短路,二进制压缩判重
考场思路:重载运算符比较字典序
错因:spfa判重数组vis,用了边权数组val
另一种方式:记录所有长度<=第k短长度的路径,取第k条
记录路径的时候,定义vector<结构体>,直接sort
vector是从0开始的!!!!
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#define N 51
using namespace std;
int n,m,k,a,b,sum;
short front[N],nxt[N*N],to[N*N],tot;
short front2[N],nxt2[N*N],to2[N*N],tot2;
int val[N*N],val2[N*N],dis[N];
queue<int>q;
struct node
{
int num,dis2;
long long go;
short cnt,road[N];
bool operator < (node p) const
{
if(dis2+dis[num]!=p.dis2+dis[p.num]) return dis2+dis[num]>p.dis2+dis[p.num];
for(int i=;i<=min(cnt,p.cnt);i++)
if(road[i]!=p.road[i]) return road[i]>p.road[i];
return cnt>p.cnt;
}
}cur,nt;
priority_queue<node>q2;
bool vis[N];
void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
}
void add(int u,int v,int w)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; val[tot]=w;
to2[++tot2]=u; nxt2[tot2]=front2[v]; front2[v]=tot2; val2[tot2]=w;
}
void spfa()
{
memset(dis,,sizeof(dis));
dis[b]=; vis[b]=true; q.push(b);
int now;
while(!q.empty())
{
now=q.front(); q.pop(); vis[now]=false;
for(int i=front[now];i;i=nxt[i])
if(dis[to[i]]>dis[now]+val[i])
{
dis[to[i]]=dis[now]+val[i];
if(!vis[to[i]])
{
vis[to[i]]=true;
q.push(to[i]);
}
}
}
}
bool have(long long x,int y)
{
if(x&(1LL<<y)) return true;
return false;
}
void solve()
{
if(dis[a]>2e9)
{
printf("No");
return;
}
if(a==b) k++;
cur.cnt=;
cur.dis2=;
cur.go=1LL<<a;
cur.num=cur.road[]=a;
q2.push(cur);
while(!q2.empty())
{
cur=q2.top(); q2.pop();
if(cur.num==b)
{
sum++;
if(sum==k)
{
printf("%d",a);
for(int i=;i<=cur.cnt;i++) printf("-%d",cur.road[i]);
return;
}
}
for(int i=front2[cur.num];i;i=nxt2[i])
if(!have(cur.go,to2[i]))
{
nt.cnt=cur.cnt+;
nt.dis2=cur.dis2+val2[i];
nt.go=cur.go|(1LL<<to2[i]);
nt.num=to2[i];
for(int j=;j<=cur.cnt;j++) nt.road[j]=cur.road[j];
nt.road[nt.cnt]=to2[i];
q2.push(nt);
}
}
printf("No");
}
int main()
{
//freopen("bzoj_1073.in","r",stdin);
//freopen("bzoj_1073.out","w",stdout);
read(n); read(m); read(k); read(a); read(b);
int u,v,w;
while(m--)
{
read(u); read(v); read(w);
add(v,u,w);
}
spfa();
solve();
}
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 51
using namespace std;
int n,m,k,a,b,sum;
short front[N],nxt[N*N],to[N*N],tot;
short front2[N],nxt2[N*N],to2[N*N],tot2;
int val[N*N],val2[N*N],dis[N];
queue<int>q;
struct node
{
int num,dis2;
long long go;
short cnt,road[N];
bool operator < (node p) const
{
return dis2+dis[num]>p.dis2+dis[p.num];
}
}cur,nt;
vector<node>ans;
priority_queue<node>q2;
bool vis[N];
void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
}
void add(int u,int v,int w)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; val[tot]=w;
to2[++tot2]=u; nxt2[tot2]=front2[v]; front2[v]=tot2; val2[tot2]=w;
}
void spfa()
{
memset(dis,,sizeof(dis));
dis[b]=; vis[b]=true; q.push(b);
int now;
while(!q.empty())
{
now=q.front(); q.pop(); vis[now]=false;
for(int i=front[now];i;i=nxt[i])
if(dis[to[i]]>dis[now]+val[i])
{
dis[to[i]]=dis[now]+val[i];
if(!vis[to[i]])
{
vis[to[i]]=true;
q.push(to[i]);
}
}
}
}
bool have(long long x,int y)
{
if(x&(1LL<<y)) return true;
return false;
}
bool cmp(node h,node g)
{
if(h.dis2!=g.dis2) return h.dis2<g.dis2;
for(int i=;i<=min(h.cnt,g.cnt);i++)
if(h.road[i]!=g.road[i]) return h.road[i]<g.road[i];
return h.cnt<g.cnt;
}
void solve()
{
if(dis[a]>2e9)
{
printf("No");
return;
}
if(a==b) k++;
cur.cnt=;
cur.dis2=;
cur.go=1LL<<a;
cur.num=cur.road[]=a;
q2.push(cur);
while(!q2.empty())
{
cur=q2.top(); q2.pop();
if(cur.num==b)
{
sum++;
ans.push_back(cur);
if(sum>k && cur.dis2>ans[k-].dis2) break;
}
for(int i=front2[cur.num];i;i=nxt2[i])
if(!have(cur.go,to2[i]))
{
nt.cnt=cur.cnt+;
nt.dis2=cur.dis2+val2[i];
nt.go=cur.go|(1LL<<to2[i]);
nt.num=to2[i];
for(int j=;j<=cur.cnt;j++) nt.road[j]=cur.road[j];
nt.road[nt.cnt]=to2[i];
q2.push(nt);
}
}
if(ans.size()>=k)
{
sort(ans.begin(),ans.end(),cmp);
printf("%d",a);
for(int i=;i<=ans[k-].cnt;i++) printf("-%d",ans[k-].road[i]);
return;
}
printf("No");
}
int main()
{
read(n); read(m); read(k); read(a); read(b);
int u,v,w;
while(m--)
{
read(u); read(v); read(w);
add(v,u,w);
}
spfa();
solve();
}
T2[ZJOI2007]最大半连通子图
Description
一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意
两点u,v,存在一条u到v的有向路径或者从v到u的有向路径。若G'=(V',E')满足V'?V,E'是E中所有跟V'有关的边,
则称G'是G的一个导出子图。若G'是G的导出子图,且G'半连通,则称G'为G的半连通子图。若G'是G所有半连通子图
中包含节点数最多的,则称G'是G的最大半连通子图。给定一个有向图G,请求出G的最大半连通子图拥有的节点数K
,以及不同的最大半连通子图的数目C。由于C可能比较大,仅要求输出C对X的余数。
Input
第一行包含两个整数N,M,X。N,M分别表示图G的点数与边数,X的意义如上文所述接下来M行,每行两个正整
数a, b,表示一条有向边(a, b)。图中的每个点将编号为1,2,3…N,保证输入中同一个(a,b)不会出现两次。N ≤1
00000, M ≤1000000;对于100%的数据, X ≤10^8
Output
应包含两行,第一行包含一个整数K。第二行包含整数C Mod X.
tarjan缩环,然后拓扑排序求最长链
注意缩环之后重新构图会出现重边,在拓扑排序里计算方案数时会多算
所以拓扑排序时判断一下是否被同一节点重复更新
错因:没有想到重边,存边的数组大小与点混淆
#include<cstdio>
#include<iostream>
#include<algorithm>
#define N 100001
#define M 1000001
using namespace std;
int mod,tot,cnt;
int front[N],nxt[M],to[M],from[M];
int front2[N],nxt2[M],to2[M],ru[N];
int dp[N][],maxn,ans;
int dfn[N],low[N],col[N],siz[N],st[N],top;
bool vis[N];
int last[N];
void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
}
void add(int u,int v)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; from[tot]=u;
}
void add2(int u,int v)
{
to2[++tot]=v; nxt2[tot]=front2[u]; front2[u]=tot; ru[v]++;
}
void tarjan(int now)
{
low[now]=dfn[now]=++tot;
st[++top]=now;
vis[now]=true;
for(int i=front[now];i;i=nxt[i])
{
if(!dfn[to[i]])
{
tarjan(to[i]);
low[now]=min(low[now],low[to[i]]);
}
else if(vis[to[i]]) low[now]=min(low[now],dfn[to[i]]);
}
if(low[now]==dfn[now])
{
cnt++;
while(top && st[top]!=now)
{
col[st[top]]=cnt;
vis[st[top]]=false;
top--;
}
col[now]=cnt;
vis[now]=false;
top--;
}
}
void topsort()
{
top=;
for(int i=;i<=cnt;i++)
if(!ru[i])
{
st[++top]=i;
dp[i][]=siz[i];
dp[i][]=;
}
int now;
while(top)
{
now=st[top]; top--;
for(int i=front2[now];i;i=nxt2[i])
{
if(dp[now][]+siz[to2[i]]>dp[to2[i]][])
{
dp[to2[i]][]=dp[now][]+siz[to2[i]];
dp[to2[i]][]=dp[now][];
last[to2[i]]=now;
}
else if(dp[now][]+siz[to2[i]]==dp[to2[i]][])
{
if(last[to2[i]]==now)
{
ru[to2[i]]--;
if(!ru[to2[i]]) st[++top]=to2[i];
continue;
}
last[to2[i]]=now;
dp[to2[i]][]+=dp[now][];
dp[to2[i]][]%=mod;
}
ru[to2[i]]--;
if(!ru[to2[i]]) st[++top]=to2[i];
}
}
}
int main()
{
int n,m;
read(n); read(m); read(mod);
int u,v;
for(int i=;i<=m;i++)
{
read(u); read(v);
add(u,v);
}
tot=;
for(int i=;i<=n;i++)
if(!dfn[i]) tarjan(i);
for(int i=;i<=n;i++) siz[col[i]]++;
tot=;
for(int i=;i<=m;i++)
if(col[from[i]]!=col[to[i]]) add2(col[from[i]],col[to[i]]);
topsort();
for(int i=;i<=cnt;i++) maxn=max(maxn,dp[i][]);
for(int i=;i<=cnt;i++)
if(maxn==dp[i][]) ans+=dp[i][],ans%=mod;
printf("%d\n%d",maxn,ans);
}
?
T3[AHOI2006]上学路线route
Description
Input
Output
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define N 501
#define M 200001
using namespace std;
int n,m;
int dis[N][N];
int e[M][];
int src,decc;
int tot=,front2[N],to2[M<<],nxt2[M<<],cap[M<<],lev[N],cur[N];
bool vis[N];
queue<int>q;
void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
}
void add2(int u,int v,int w)
{
to2[++tot]=v; nxt2[tot]=front2[u]; front2[u]=tot; cap[tot]=w;
to2[++tot]=u; nxt2[tot]=front2[v]; front2[v]=tot; cap[tot]=;
}
void build()
{
for(int k=;k<=n;k++)
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
if(k!=i && i!=j && k!=j)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
int minn=dis[][n];
printf("%d\n",minn);
for(int i=;i<=m;i++)
{
if(dis[][e[i][]]+e[i][]+dis[e[i][]][n]==minn)
add2(e[i][],e[i][],e[i][]);
if(dis[][e[i][]]+e[i][]+dis[e[i][]][n]==minn)
add2(e[i][],e[i][],e[i][]);
} }
bool spfa2()
{
for(int i=;i<=n;i++) cur[i]=front2[i],lev[i]=-;
while(!q.empty()) q.pop();
lev[]=; q.push();
int now;
while(!q.empty())
{
now=q.front(); q.pop();
for(int i=front2[now];i;i=nxt2[i])
if(lev[to2[i]]==- && cap[i]>)
{
lev[to2[i]]=lev[now]+;
if(to2[i]==n) return true;
q.push(to2[i]);
}
}
return false;
}
int dinic(int now,int flow)
{
if(now==n) return flow;
int delta,rest=;
for(int & i=cur[now];i;i=nxt2[i])
if(lev[to2[i]]>lev[now] && cap[i]>)
{
delta=dinic(to2[i],min(cap[i],flow-rest));
if(delta)
{
cap[i]-=delta; cap[i^]+=delta;
rest+=delta; if(rest==flow) break;
}
}
if(rest!=flow) lev[now]=-;
return rest;
}
int main()
{
read(n); read(m);
int u,v,t,c;
memset(dis,,sizeof(dis));
for(int i=;i<=n;i++) dis[i][i]=;
for(int i=;i<=m;i++)
{
read(u); read(v); read(t); read(c);
e[i][]=u; e[i][]=v; e[i][]=t; e[i][]=c;
dis[u][v]=dis[v][u]=min(dis[u][v],t);
}
build();
int ans=;
while(spfa2())
ans+=dinic(,2e9);
printf("%d",ans);
}
NOIP模拟2的更多相关文章
- NOIP模拟赛20161022
NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...
- contesthunter暑假NOIP模拟赛第一场题解
contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...
- NOIP模拟赛 by hzwer
2015年10月04日NOIP模拟赛 by hzwer (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...
- 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程
数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...
- 队爷的讲学计划 CH Round #59 - OrzCC杯NOIP模拟赛day1
题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的讲学计划 题解:刚开始理解题意理解了好半天,然后发 ...
- 队爷的Au Plan CH Round #59 - OrzCC杯NOIP模拟赛day1
题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的Au%20Plan 题解:看了题之后觉得肯定是DP ...
- 队爷的新书 CH Round #59 - OrzCC杯NOIP模拟赛day1
题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的新书 题解:看到这题就想到了 poetize 的封 ...
- CH Round #58 - OrzCC杯noip模拟赛day2
A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...
- CH Round #52 - Thinking Bear #1 (NOIP模拟赛)
A.拆地毯 题目:http://www.contesthunter.org/contest/CH%20Round%20%2352%20-%20Thinking%20Bear%20%231%20(NOI ...
- CH Round #49 - Streaming #4 (NOIP模拟赛Day2)
A.二叉树的的根 题目:http://www.contesthunter.org/contest/CH%20Round%20%2349%20-%20Streaming%20%234%20(NOIP 模 ...
随机推荐
- 欢迎来怼-----Beta冲刺贡献分数分配结果
队名:欢迎来怼 小组成员 队长:田继平 成员:李圆圆,葛美义,王伟东,姜珊,邵朔,阚博文
- 浅析GCC下C++多重继承 & 虚拟继承的对象内存布局
继承是C++作为OOD程序设计语言的三大特征(封装,继承,多态)之一,单一非多态继承是比较好理解的,本文主要讲解GCC环境下的多重继承和虚拟继承的对象内存布局. 一.多重继承 先看几个类的定义: 01 ...
- Markdown语法实践
Markdown语法实践 Markdown基本语法 1.标题 # 一级标题 ## 二级标题 ### 三级标题 eg: 一级标题 二级标题 三级标题 2.链接 标准: [Title](URL) 实例: ...
- [Oracle收费标准]
http://www.oracle.com/us/corporate/pricing/technology-price-list-070617.pdf 1: 数据库 2. 中间件 3. weblogi ...
- php面试必知必会常见问题
1 说出常用的10个数组方法 我觉得数组比较最能体现PHP基础语法的一个数据结构了,下面给大家列一下常用的10个关于操作数组的函数 in_array(判断数组中是否有某个元素) implode(将数组 ...
- Mysql中关键词执行顺序
MySQL的语句执行顺序 MySQL的语句一共分为11步,最先执行的总是FROM操作,最后执行的是LIMIT操作.其中每一个操作都会产生一张虚拟的表,这个虚拟的表作为一个处理的输入,只是这些虚拟的表对 ...
- jmeter 安装tps插件
1.下载 jpgc-graphs-basic-2.0.zip 2.解压并将lib 目录下的 jmeter-plugins-cmn-jmeter-0.4.jar 拷贝到 %JMeter%/lib 目录 ...
- SSH管理(重启 停止 运行 安装)centos7
下面整理经常用到管理SSH服务的命令,方便复制哈. SSH服务状态 systemctl status sshd.service SSH运行命令 service sshd start SSH重启命令 s ...
- 第187天:js基础---常见的Bom对象
BOM(Browser Object Mode)浏览器对象模型,是Javascript的重要组成部分.它提供了一系列对象用于与浏览器窗口进行交互,这些对象通常统称为BOM. 一张图了解一下先 1.wi ...
- FZU2127_养鸡场
题目的意思为要你求出满足三边范围条件且周长为n的三角形的数目. 其实做法是直接枚举最短边,然后就可以知道第二条边的取值范围,同时根据给定的范围缩小范围. 同时根据第二条边的范围推出第三条边的范围,再次 ...