poj 2455
题意:由一个点走到另一个点,中间的点可以重复到达,但边只能经过一次,问T条边不重复的路径里,最长的边的最小值.
分析:由于点是可以重用的,因此不必拆点.这道题有重边,而且重边都必须保留,因为点是可以重复走的.二分最长的边长,用最大流来验证.
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 const int MAXN=205;//点数的最大值 5 const int MAXM=160005;//边数的最大值 6 const int INF=0x3fffffff; 7 8 struct Node 9 { 10 int from,to,next; 11 int cap; 12 }edge[MAXM]; 13 14 int tol; 15 int head[MAXN]; 16 int dep[MAXN]; 17 int gap[MAXN];//gap[x]=y :说明残留网络中dep[i]==x的个数为y 18 int n;//n是总的点的个数,包括源点和汇点 19 Node container[40005]; 20 21 void init() 22 { 23 tol=0; 24 memset(head,-1,sizeof(head)); 25 } 26 27 void addedge(int u,int v,int w) 28 { 29 edge[tol].from=u; 30 edge[tol].to=v; 31 edge[tol].cap=w; 32 edge[tol].next=head[u]; 33 head[u]=tol++; 34 edge[tol].from=v; 35 edge[tol].to=u; 36 edge[tol].cap=0; 37 edge[tol].next=head[v]; 38 head[v]=tol++; 39 } 40 void BFS(int start,int end) 41 { 42 memset(dep,-1,sizeof(dep)); 43 memset(gap,0,sizeof(gap)); 44 gap[0]=1; 45 int que[MAXN]; 46 int front,rear; 47 front=rear=0; 48 dep[end]=0; 49 que[rear++]=end; 50 while(front!=rear) 51 { 52 int u=que[front++]; 53 if(front==MAXN)front=0; 54 for(int i=head[u];i!=-1;i=edge[i].next) 55 { 56 int v=edge[i].to; 57 if(dep[v]!=-1)continue; 58 que[rear++]=v; 59 if(rear==MAXN)rear=0; 60 dep[v]=dep[u]+1; 61 ++gap[dep[v]]; 62 } 63 } 64 } 65 int SAP(int start,int end) 66 { 67 int res=0; 68 BFS(start,end); 69 int cur[MAXN]; 70 int S[MAXN]; 71 int top=0; 72 memcpy(cur,head,sizeof(head)); 73 int u=start; 74 int i; 75 while(dep[start]<n) 76 { 77 if(u==end) 78 { 79 int temp=INF; 80 int inser; 81 for(i=0;i<top;i++) 82 if(temp>edge[S[i]].cap) 83 { 84 temp=edge[S[i]].cap; 85 inser=i; 86 } 87 for(i=0;i<top;i++) 88 { 89 edge[S[i]].cap-=temp; 90 edge[S[i]^1].cap+=temp; 91 } 92 res+=temp; 93 top=inser; 94 u=edge[S[top]].from; 95 } 96 if(u!=end&&gap[dep[u]-1]==0)//出现断层,无增广路 97 break; 98 for(i=cur[u];i!=-1;i=edge[i].next) 99 if(edge[i].cap!=0&&dep[u]==dep[edge[i].to]+1) 100 break; 101 if(i!=-1) 102 { 103 cur[u]=i; 104 S[top++]=i; 105 u=edge[i].to; 106 } 107 else 108 { 109 int min=n; 110 for(i=head[u];i!=-1;i=edge[i].next) 111 { 112 if(edge[i].cap==0)continue; 113 if(min>dep[edge[i].to]) 114 { 115 min=dep[edge[i].to]; 116 cur[u]=i; 117 } 118 } 119 --gap[dep[u]]; 120 dep[u]=min+1; 121 ++gap[dep[u]]; 122 if(u!=start)u=edge[S[--top]].from; 123 } 124 } 125 return res; 126 } 127 int main() 128 { 129 int N,P,T; 130 while(~scanf("%d%d%d",&N,&P,&T)) 131 { 132 n = N; 133 int left = INF,right = 0; 134 for(int i = 0;i < P;i++) 135 { 136 scanf("%d%d%d",&container[i].from,&container[i].to,&container[i].cap); 137 left = std::min(container[i].cap,left); 138 right = std::max(container[i].cap,right); 139 } 140 left--; 141 while(left + 1 < right) 142 { 143 int mid = (left + right) / 2; 144 init(); 145 for(int i = 0;i < P;i++) 146 { 147 if(container[i].cap <= mid) 148 { 149 addedge(container[i].from,container[i].to,1); 150 addedge(container[i].to,container[i].from,1); 151 } 152 } 153 if(SAP(1,n) >= T) 154 { 155 right = mid; 156 } 157 else 158 { 159 left = mid; 160 } 161 } 162 printf("%d\n",right); 163 } 164 return 0; 165 }