这道题做了两个小时,做的我都快崩溃了。。。先是没有发现两个点之间可以有多条边,然后又忽略了是双向边,无比郁闷啊。看来读题也是一个能力啊,我太弱了。。。
题目给出N个点和P条边,(两个点之间可能有多条边),然后问如果想要从1走到N走T次并且每条路只能走一次的话,求所走过的路中最长的边的最小值。
我们可以用最大流来解决这个问题,首先考虑不重复的走T次,只需使每条路的容量为1就好,然后看容量能不能达到T。为了求最长边的最小值,我们可以二分最长边,先对所有边进行排序,然后每次对长度在该次二分长度之内的边容量设为1,求最大流。
- #include <cstdio>
- #include <cstring>
- #include <queue>
- #include <algorithm>
- #define min(a,b) ((a)<(b)?(a):(b))
- #define INF 0x1f1f1f1f
- #define MAXN 220
- using namespace std;
- int cap[MAXN][MAXN],f[MAXN][MAXN],level[MAXN],q[MAXN];
- int src,sink,n,limit,m,t;
- struct Edge{
- int u,v,dist;
- Edge(){}
- Edge(int _u,int _v,int _dist):u(_u),v(_v),dist(_dist){}
- bool operator<(const Edge &n)const{
- return dist < n.dist;
- }
- }edge[MAXN*MAXN];
- inline bool dinic_bfs(){
- int queue[MAXN];
- memset(level,-1,sizeof(level));
- int tail = 0,head = 0;
- queue[tail++] = src;
- level[src] = 0;
- while(tail > head){
- int tep = queue[head++];
- for(int i = 1;i <= n; ++i){
- if(level[i] == -1 && cap[tep][i] > f[tep][i]){
- level[i] = level[tep] + 1;
- queue[tail++] = i;
- }
- }
- }
- return level[sink] != -1;
- }
- inline int dinic(){
- int tail,cur,m,k;
- int maxflow = 0, *stack = q;
- while(dinic_bfs()){
- tail = 0;
- stack[tail++] = src;
- while(tail){
- cur = stack[tail-1];
- if(cur == sink){
- m = INF;
- for(int i = 1;i < tail; ++i){
- if(m > cap[stack[i-1]][stack[i]] - f[stack[i-1]][stack[i]]){
- m = cap[stack[i-1]][stack[i]] - f[stack[i-1]][stack[i]];
- k = i;
- }
- }
- maxflow += m;
- for(int i = 1;i < tail; ++i){
- f[stack[i-1]][stack[i]] += m;
- f[stack[i]][stack[i-1]] -= m;
- }
- tail = k;
- }
- else{
- int i;
- for(i = 1;i <= n; ++i){
- if(level[i] == level[cur] + 1 && cap[cur][i] > f[cur][i]){
- stack[tail++] = i;;
- break;
- }
- }
- if(i == n+1){
- level[cur] = -1;
- --tail;
- }
- }
- }
- }
- return maxflow;
- }
- inline void rebuild(int mid){
- memset(f,0,sizeof(f));
- memset(cap,0,sizeof(cap));
- for(int i = 1;i <= mid; ++i){
- cap[edge[i].u][edge[i].v] ++;
- cap[edge[i].v][edge[i].u] ++;
- }
- }
- int main()
- {
- int u,v,w,high,low;
- while(scanf("%d%d%d",&n,&m,&t) != EOF){
- memset(f,0,sizeof(f));
- memset(cap,0,sizeof(cap));
- src = 1; sink = n;
- for(int i = 1;i <= m; i++){
- scanf("%d%d%d",&u,&v,&w);
- edge[i] = Edge(u,v,w);
- }
- sort(edge+1,edge+m+1);
- low = 1; high = m;
- int mid,flow,ans = INF;
- while(high >= low){
- mid = (high + low)/2;
- rebuild(mid);
- flow = dinic();
- if(flow >= t){
- high = mid - 1;
- if(edge[mid].dist < ans) ans = edge[mid].dist;
- }
- else low = mid + 1;
- }
- //printf("m = %d and low = %d/n",m,low);
- printf("%d/n",ans);
- }
- }