SGU 185 Two shortest 最短路+最大流

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=21068

Yesterday Vasya and Petya quarreled badly, and now they don't want to see each other on their way to school. The problem is that they live in one and the same house, leave the house at the same time and go at the same speed by the shortest road. Neither of them wants to change their principles, that is why they want to find two separate shortest routes, which won't make them go along one road, but still they can meet at any junction. They ask you to help them. They number all the junctions with numbers from 1 to N (home and school are also considered as junctions). So their house has the number 1 and the school has the number N, each road connects two junctions exactly, and there cannot be several roads between any two junctions.

题意描述:有n个节点,找出1~n的两条不相交的最短路(两条路径可以共点不能共边)。

算法分析:用spfa求出点1到各个点的最短路径,然后再if(d[j]==d[i]+dis[i][j]) 来判断边dis[i][j]是否是在最短路径上,如果是就加到图里,结果就得到以1为顶点的最短路径树,1到树中任意一点的连线都是最短路径,首先把这些边加到网络流的边集中,容量为1。跑一遍1到n的最大流,如果流量>=2则有解,再从原点深搜路径即可。

说明:这道题很卡内存和时间,MLE!MLE!MLE!M出翔了。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<cmath>
  6 #include<algorithm>
  7 #include<queue>
  8 #include<vector>
  9 #define inf 10737418
 10 using namespace std;
 11 typedef long long ll;
 12 const int maxn=400+10;
 13 const int M = 120000+10;
 14 
 15 int n,m,from,to;
 16 struct Edge
 17 {
 18     int to,cap;
 19     int next;
 20 }edge[M*2];
 21 int head[maxn],edgenum;
 22 
 23 void add(int u,int v,int cap)
 24 {
 25     Edge E={v,cap,head[u]};
 26     edge[edgenum]=E;
 27     head[u]=edgenum++;
 28 
 29     Edge E2={u,0,head[v]};
 30     edge[edgenum]=E2;
 31     head[v]=edgenum++;
 32 }
 33 
 34 int d[maxn];
 35 bool BFS()
 36 {
 37     memset(d,-1,sizeof(d));
 38     d[from]=0;
 39     queue<int> Q;
 40     Q.push(from);
 41     while (!Q.empty() ){
 42         int u=Q.front(); Q.pop();
 43         for (int i=head[u] ;i!=-1 ;i=edge[i].next)
 44         {
 45             int v=edge[i].to;
 46             if (d[v]==-1 && edge[i].cap)
 47             {
 48                 d[v]=d[u]+1,Q.push(v);
 49                 if (d[to] != -1) return true;
 50             }
 51         }
 52     }
 53     return false;
 54 }
 55 int Stack[maxn], top, cur[maxn];
 56 int Dinic(){
 57     int ans=0;
 58     while(BFS())
 59     {
 60         memcpy(cur, head, sizeof(head));
 61         int u = from;      top = 0;
 62         while(1)
 63         {
 64             if(u == to)
 65             {
 66                 int flow = inf, loc;//loc 表示 Stack 中 cap 最小的边
 67                 for(int i = 0; i < top; i++)
 68                     if(flow > edge[ Stack[i] ].cap)
 69                     {
 70                         flow = edge[Stack[i]].cap;
 71                         loc = i;
 72                     }
 73 
 74                     for(int i = 0; i < top; i++)
 75                     {
 76                         edge[ Stack[i] ].cap -= flow;
 77                         edge[Stack[i]^1].cap += flow;
 78                     }
 79                     ans += flow;
 80                     top = loc;
 81                     u = edge[Stack[top]^1].to;
 82             }
 83             for(int i = cur[u]; i!=-1; cur[u] = i = edge[i].next)//cur[u] 表示u所在能增广的边的下标
 84                 if(edge[i].cap && (d[u] + 1 == d[ edge[i].to ]))break;
 85             if(cur[u] != -1)
 86             {
 87                 Stack[top++] = cur[u];
 88                 u = edge[ cur[u] ].to;
 89             }
 90             else
 91             {
 92                 if( top == 0 )break;
 93                 d[u] = -1;
 94                 u = edge[ Stack[--top]^1 ].to;
 95             }
 96         }
 97     }
 98     return ans;
 99 }
100 int dis[maxn][maxn];
101 int vis[maxn];
102 void spfa()
103 {
104     for (int i=1 ;i<=n ;i++) d[i]=inf;
105     d[1]=0;
106     memset(vis,0,sizeof(vis));
107     queue<int> Q;
108     Q.push(1);
109     vis[1]=1;
110     while (!Q.empty())
111     {
112         int u=Q.front() ;Q.pop() ;
113         vis[u]=0;
114         for (int v=1 ;v<=n ;v++)
115         {
116             if (d[v]>d[u]+dis[u][v])
117             {
118                 d[v]=d[u]+dis[u][v];
119                 if (!vis[v])
120                 {
121                     vis[v]=1;
122                     Q.push(v);
123                 }
124             }
125         }
126     }
127 }
128 void dfs(int u, int fa)
129 {
130     if (u == n){printf("%d\n",u);return ;}
131     else printf("%d ",u);
132     for (int i = head[u] ;i!=-1 ;i=edge[i].next)
133     {
134         if (edge[i^1].cap != 1 || (i&1)) continue;
135         int v=edge[i].to;
136         if (v == fa) continue;
137         edge[i^1].cap=0;
138         dfs(v, u);
139         return;
140     }
141 }
142 
143 int main()
144 {
145     while (scanf("%d%d",&n,&m)!=EOF)
146     {
147         memset(head,-1,sizeof(head));
148         edgenum=0;
149         int a,b,c;
150         for (int i=1 ;i<=n ;i++)
151             for (int j=1 ;j<=n ;j++)
152                 dis[i][j]=inf;
153         for (int i=0 ;i<m ;i++)
154         {
155             scanf("%d%d%d",&a,&b,&c);
156             dis[a][b] = dis[b][a] = min(dis[a][b], c);
157         }
158         spfa();
159         if (d[n]==inf) {printf("No solution\n");continue; }
160         from=1;
161         to=n+1;
162         for (int i=1 ;i<=n ;i++)
163         {
164             for (int j=1 ;j<=n ;j++)
165             {
166                 if(dis[i][j]!=inf && d[j] == dis[i][j] + d[i])
167                     add(i,j,1);
168             }
169         }
170         add(n,to,2);
171         int sum=Dinic();
172         if (sum<2) {printf("No solution\n");continue; }
173         dfs(1,1);
174         dfs(1,1);
175     }
176     return 0;
177 }

 

转载于:https://www.cnblogs.com/huangxf/p/4372984.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值