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 }

 

posted @ 2013-08-03 10:08  Hogg  阅读(299)  评论(0编辑  收藏  举报