图论专题测试 【最短路】【网络流】解题报告
来源:互联网 发布:iphone移动数据 编辑:程序博客网 时间:2024/06/08 06:18
今天进行了一个测试。比上次简单些。。。
第一题
思路
找一个最短路的值,还要记录路径。SPFA再跑一遍找一下还有哪些路径。但是注意,会被卡的!加了优化还是只有60分。所以就看看代码吧。
代码
先是我的:
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cmath>#include<vector>#include<queue>using namespace std;const int N=300+5;const int M=1e5;const int INF=1e5*N;int n,m,ans=1,flag[N],dis[N],pre[N],head[N],num;deque<int> q;struct edge{ int u,v,w,next; edge(){next=-1;}}ed[M+5];void build(int u,int v,int w){ ed[++num].u=u; ed[num].v=v; ed[num].w=w; ed[num].next=head[u]; head[u]=num;}int SPFA(int s,int e){ for (int i=1;i<=n;i++) dis[i]=(i==s)?0:INF,flag[i]=(i==s)?1:0; while(!q.empty())q.pop_front(); q.push_back(s); while(!q.empty()) { int u=q.front();q.pop_front(); flag[u]=0; for (int i=head[u];i!=-1;i=ed[i].next) { int v=ed[i].v; if (dis[v]>dis[u]+ed[i].w) { dis[v]=dis[u]+ed[i].w; pre[v]=i; if (!flag[v]) { flag[v]=1; if (!q.empty()) { if (dis[v]>dis[q.front()])q.push_back(v); else q.push_front(v); } else q.push_back(v); } } } } return dis[e];}int main(){ freopen("change.in","r",stdin); freopen("change.out","w",stdout); memset(head,-1,sizeof(head)); scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); build(u,v,w); } int minn=SPFA(1,n); while(true) { for (int u=n;u!=1;u=ed[pre[u]].u) ed[pre[u]].w=INF; int _minn=SPFA(1,n); if (minn==_minn)ans++; else break; } printf("%d",ans); return 0;}
然后:
#include<stdio.h>#include<cstring>#include<algorithm>#include<queue>#include<map>using namespace std;struct edge{ int v,last,mrk,u,w;}ed[400010];priority_queue < pair<int,int> ,vector< pair<int,int> > ,greater<pair<int,int> > > state;int head[100010],se[100010],dis[100010],frm[400010];int n,m,ans,bns,cns,num=0,INF=1e9+7;void add(int u,int v,int w){ num++; ed[num].v=v; ed[num].w=w; ed[num].u=u; ed[num].mrk=0; ed[num].last=head[u]; head[u]=num;}int spfa(int flag){ memset(frm,0,sizeof(frm)); memset(se,0,sizeof(se)); while(!state.empty()) state.pop(); for(int i=1;i<=n;i++) dis[i]=INF; state.push(make_pair(0,1)); se[1]=1,dis[1]=0; while(!state.empty()) { int u=state.top().second; se[u]=0; state.pop(); for(int i=head[u];i;i=ed[i].last) if(ed[i].mrk==0) { int v=ed[i].v; if(dis[v]>dis[u]+ed[i].w) { dis[v]=dis[u]+ed[i].w; frm[v]=i; if(!se[v]) { state.push(make_pair(dis[v],v)); se[v]=1; } } } } if(flag==0) cns=dis[n]; int p=frm[n]; while(p) { ed[p].mrk=1; p=frm[ed[p].u]; } return dis[n];}void sov(int flag){ int bns; while(1) { bns=spfa(flag); if(bns!=cns) break ; flag++,ans++; }}int main(){ freopen("change.in","r",stdin); freopen("change.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w); } sov(0); printf("%d",ans);}/*Whoso pulleth out this sword from this stone and anvil is duly born King of all England*/
第二题
思路:
网络流。二分等级,把比这个mid小的加上。然后分奇偶(注意特判2)建图,边上记录火力值,然后二分图之间是INF,跑一边最大流最小割就好了。具体看代码。
代码
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<vector>#include<queue>using namespace std;const int INF=0x3f3f3f3f;const int N=5e5+5;struct edge{ int v,w,last;}ed[2*N];int head[N],dis[N],tim[N],pow[N],l[N],primes[4*N],isnot[4*N],x[4*N];int n,k,num=1,cns,S,T,big=0,ptot=0;int min(int x,int y){ if (x<=y) return x; else return y;}int max(int x,int y){ if (x>=y) return x; else return y;}void build(int u,int v,int w){ num++; ed[num].v=v; ed[num].w=w; ed[num].last=head[u]; head[u]=num;}void getphi(int n){ isnot[1]=1; for (int i=2;i<=n;i++) if (!isnot[i]) { primes[ptot++]=i; for (int j=i+i;j<=n;j+=i) isnot[j]=1; }}int bfs(){ queue<int> state; memset(dis,-1,sizeof(dis)); state.push(S); dis[S]=0; while(!state.empty()) { int u=state.front(); state.pop(); for (int i=head[u];i;i=ed[i].last) { int v=ed[i].v; if (dis[v]==-1&&ed[i].w>0) { dis[v]=dis[u]+1; state.push(v); } } } if (dis[T]==-1) return 0; return 1;}int dfs(int u,int low){ int a=0; if (u==T) return low; for (int i=head[u];i;i=ed[i].last) { int v=ed[i].v; if (ed[i].w>0&&dis[v]==dis[u]+1) { int tmp=dfs(v,min(low-a,ed[i].w)); ed[i].w-=tmp,ed[i^1].w+=tmp; a+=tmp; } } return a;}int main(){ freopen("card.in","r",stdin); freopen("card.out","w",stdout); getphi(1000005); scanf("%d%d",&n,&k); for (int i=1;i<=n;i++) { scanf("%d%d%d",&pow[i],&tim[i],&l[i]); big=max(big,l[i]); } int lf=1,rg=1e9+7,ans=-1; while(lf<=rg) { memset(head,0,sizeof(head)); memset(x,0,sizeof(x)); int mid=(lf+rg)>>1,big=0,tar,t=0,tot=0; num=1,cns=0; for (int i=1;i<=n;i++) if (l[i]<=mid&&pow[i]>big&&tim[i]==1) big=pow[i],tar=i; for (int i=1;i<=n;i++) if (l[i]<=mid&&(i==tar||tim[i]>1)) { x[++t]=i; tot+=pow[i]; } S=0,T=t+2;//建立汇点源点 for (int i=1;i<=t;i++) if (tim[x[i]]&1) { build(S,i,pow[x[i]]); build(i,S,0); }//奇数建边 else { build(i,T,pow[x[i]]); build(T,i,0); }//偶数建边 for (int i=1;i<=t;i++) if (tim[x[i]]&1) for (int j=1;j<=t;j++) if ((~tim[x[j]]&1)&&!isnot[tim[x[i]]+tim[x[j]]]) { build(i,j,INF); build(j,i,0); }//特判 while(bfs()) { int bns=0; while(bns=dfs(S,INF)) tot-=bns; } if (tot>=k) rg=(ans=mid)-1; else lf=mid+1; } printf("%d",ans); return 0;}
第三题
思路
SPFA找最短路。一样要优化!分成两种,一种是灵力,一种是时间。用tarjan找强连通分量(因为只有这样会产生“眩晕”),再最短路。
刚开始找强连通分量用的是SPFA。。。又被卡了。。。
代码
#include<queue>#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<cmath>using namespace std;const int N=1e5+5;int n,m,head[N],num,dfn[N],low[N],con[N],sta[N],flag[N],top,tim;long long dis[N];long long cost[N];struct edge{ int v,w; int next; edge(){next=-1;}}ed[N+5];void build(int u,int v,int w){ ed[++num].v=v; ed[num].w=w; ed[num].next=head[u]; head[u]=num;}void tarjan(int u){ dfn[u]=low[u]=++tim; flag[sta[++top]=u]=1; for (int i=head[u];i!=-1;i=ed[i].next) { int v=ed[i].v; if (!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if (flag[v])low[u]=min(low[u],dfn[v]); } if (dfn[u]==low[u]) for (int now=0;now!= u;) { flag[now=sta[top--]]=0; con[now]=u; }}void SPFA(){ deque<int> q; memset(flag,0,sizeof flag); memset(dis,-1,sizeof dis); memset(cost,-1,sizeof cost); q.push_back(1);dis[1]=0,cost[1]=0; while(!q.empty()) { int u=q.front(); q.pop_front(); flag[u]=0; for (int i=head[u];i!=-1;i=ed[i].next) { int v=ed[i].v; int cc=con[v]==con[u]?cost[u]+1:cost[u]; if (cost[v]>cc||cost[v]==-1||(dis[v]>dis[u]+ed[i].w&&cost[v]==cc)||(dis[v]==-1&&cost[v]==cc)) { cost[v]=cc; dis[v]=dis[u]+ed[i].w; if (!flag[v]) { flag[v]=1; if (!q.empty()) { if (dis[v]>dis[q.front()])q.push_back(v); else q.push_front(v); } q.push_back(v); } } } }}int main(){ freopen("festival.in","r",stdin); freopen("festival.out","w",stdout); memset(head,-1,sizeof(head)); scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); build(v,u,w); } for (int i=1;i<=n;i++) if (!con[i])tarjan(i); SPFA(); for (int k=2;k<=n;k++) { if (dis[k]==dis[0]) printf("-1\n"); else printf("%I64d %I64d\n",cost[k],dis[k]); } return 0;}
以上
阅读全文
2 0
- 图论专题测试 【最短路】【网络流】解题报告
- 【最短路】解题报告
- 图论专题(二)POJ1125最短路
- 图论专题总结—最短路
- 图论专题小结:最短路算法
- 最短路入门练习 解题报告
- HDU2544 最短路 解题报告--Dijkstra
- 解题报告 之 HDU2544 最短路
- hdu2544 最短路(floyd) 解题报告
- hdu2544 最短路(Dijkstra) 解题报告
- 最短路spfaPOJInvitation Cardsj解题报告
- hdu 2544 最短路 spfa 解题报告
- hdu 2544 最短路 Bellman_Ford 解题报告
- Hdu 3986 【枚举】【最短路】 解题报告
- BZOJ 1003 DP+最短路 解题报告
- POJ1724 ROADS 解题报告【最短路/SPFA】
- 图论专题(三)POJ1135最短路骨诺牌
- HDU 3339 In Action 解题报告(最短路+背包)
- 《Flask Web开发》学习笔记之bug--(1)【404 Not Found】
- All in All POJ
- 什么是P问题、NP问题和NPC问题
- python修炼计划 从基本学起1
- Android 自定义View (一)
- 图论专题测试 【最短路】【网络流】解题报告
- 微信小程序中的eCharts
- Keepalived 的安装和配置
- Java基础之基本IO操作
- siege工具源码解析
- ESP8266 作为Server进行TCP通信
- 概率论-随机向量及其分布
- Spring Cloud学习系列_3参数引入、多环境配置、加载顺序
- SpringBoot HelloWorld