题意:有N个农场,P条无向路连接。要从1到N不重复走T条路,求所经过的直接连接两个区域的道路中最长道路中的最小值,。
构图:源点向1连容量T的边。二分最小长度,长度超过mid的边容量为0,否则为1,用最大流判可行性。
注意:1.该题有重边,切忌用邻接矩阵删除重边(重边要用邻接表来处理以保留)。2.无向图在addedge中要进行处理(处理方式见代码)。
View Code
/*Source Code Problem: 2455 User: HEU_daoguang Memory: 2440K Time: 188MS Language: G++ Result: Accepted Source Code*/ #include <iostream> #include <string.h> #include <stdio.h> using namespace std; #define V 250 #define E 40050 #define inf 0x3f3f3f3f int map[V][V]; struct Edge { int u,v,c,next; }edge[2*E]; struct TEdge { int u,v,c; }ed[2*E]; int n,p,cnt; int dist[V]; int head[V]; int que[V]; int sta[V]; int s,t; void init(){ cnt=0; memset(head,-1,sizeof(head)); } void addedge(int u,int v,int c){ edge[cnt].u=u;edge[cnt].v=v;edge[cnt].c=c; edge[cnt].next=head[u];head[u]=cnt++; edge[cnt].u=v;edge[cnt].v=u;edge[cnt].c=c;//无向图edge[cnt].c=c,有向图edge[cnt].c=0; edge[cnt].next=head[v];head[v]=cnt++; } int dinic(int s,int t){ int ans=0; while(true){ int left,right,u,v; memset(dist,-1,sizeof(dist)); left=right=0; que[right++]=s; dist[s]=0; while(left<right){ u=que[left++]; for(int k=head[u];k!=-1;k=edge[k].next){ u=edge[k].u; v=edge[k].v; if(edge[k].c > 0 && dist[v]==-1){ dist[v]=dist[u]+1; que[right++]=v; if(v==t){ left=right; break; } } } } if(dist[t]==-1) break; int top=0; int now=s; while(true){ if(now!=t){ int k; for(k=head[now];k!=-1;k=edge[k].next){ if(edge[k].c>0 && dist[edge[k].v]==dist[edge[k].u]+1) break; } if(k!=-1){ sta[top++]=k; now=edge[k].v; } else{ if(top==0) break; dist[edge[sta[--top]].v]=-1; now=edge[sta[top]].u; } } else{ int flow=inf,ebreak; for(int i=0;i<top;i++){ if(flow>edge[sta[i]].c){ flow=edge[sta[i]].c; ebreak=i; } } ans+=flow; for(int i=0;i<top;i++){ edge[sta[i]].c-=flow; edge[sta[i]^1].c+=flow; } now=edge[sta[ebreak]].u; top=ebreak; } } } return ans; } int main() { //freopen("in.txt","r",stdin); int t,a,b,c,minc,maxc,ans; while(scanf("%d%d%d",&n,&p,&t)!=EOF){ minc=inf ,maxc=-1; for(int i=1;i<=p;i++){ scanf("%d%d%d",&ed[i].u,&ed[i].v,&ed[i].c); minc=min(minc,ed[i].c); maxc=max(maxc,ed[i].c); } int l=minc,r=maxc,mid; while(l<r){ mid=(l+r)/2; //cout << mid << endl; init(); addedge(0,1,t); for(int i=1;i<=p;i++){ if(ed[i].c<=mid) addedge(ed[i].u,ed[i].v,1); } int res=dinic(0,n); if(res>=t){ r=mid; } else l=mid+1; } cout << r << endl; } return 0; }
吐槽:优化到188ms用了整整24小时,有木有?太菜了,有木有?