题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1760
题意:给定一个带权有向图 G=(V, E)和源点 s、汇点 t,问 s-t 边不相交最短路最多有几
条。(1 <= N <= 100)
思路:分别从源点和汇点作一次 Dijkstra,可是流量网络仅仅增加
满足dis[i] + ma[i][j] + (dis[t]-dis[i])==dis[t]的边(u, v)(这样便保证网络中的随意一条 s-t 路都
是最短路),容量为 1。求最大流。
忘记加不存在最短路的情况了,没写 inf 了,今天看到了,加了三行, 要不昨晚就A了。。。。
#include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <queue> #include <algorithm> const int N = 210; const int maxn = 2000; const int maxm = 100000; #define MIN INT_MIN #define MAX 1e6 #define LL long long #define FOR(i,a,b) for(int i = a;i<b;i++) #define max(a,b) (a>b)?(a):(b) #define min(a,b) (a>b)?(b):(a) using namespace std; int head[maxn], bnum; int dis[maxn]; int num[maxn]; int cur[maxn]; int pre[maxn]; int ma[310][310],di[310],vis[310]; struct node { int v, cap; int next; } edge[maxm]; void add(int u, int v, int cap) { edge[bnum].v=v; edge[bnum].cap=cap; edge[bnum].next=head[u]; head[u]=bnum++; edge[bnum].v=u; edge[bnum].cap=0; edge[bnum].next=head[v]; head[v]=bnum++; } void BFS(int source,int sink) { // puts("worinimeiaaaa"); queue<int>q; while(q.empty()==false) q.pop(); memset(num,0,sizeof(num)); memset(dis,-1,sizeof(dis)); q.push(sink); dis[sink]=0; num[0]=1; while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u]; i!=-1; i=edge[i].next) { int v = edge[i].v; if(dis[v] == -1) { dis[v] = dis[u] + 1; num[dis[v]]++; q.push(v); } } } } int ISAP(int source,int sink,int n) { // puts("wonimeia"); memcpy(cur,head,sizeof(cur)); int flow=0, u = pre[source] = source; BFS( source,sink); while( dis[source] < n ) { if(u == sink) { int df = MAX, pos; for(int i = source; i != sink; i = edge[cur[i]].v) { if(df > edge[cur[i]].cap) { df = edge[cur[i]].cap; pos = i; } } for(int i = source; i != sink; i = edge[cur[i]].v) { edge[cur[i]].cap -= df; edge[cur[i]^1].cap += df; } flow += df; u = pos; } int st; for(st = cur[u]; st != -1; st = edge[st].next) { if(dis[edge[st].v] + 1 == dis[u] && edge[st].cap) { break; } } if(st != -1) { cur[u] = st; pre[edge[st].v] = u; u = edge[st].v; } else { if( (--num[dis[u]])==0 ) break; int mind = n; for(int id = head[u]; id != -1; id = edge[id].next) { if(mind > dis[edge[id].v] && edge[id].cap != 0) { cur[u] = id; mind = dis[edge[id].v]; } } dis[u] = mind+1; num[dis[u]]++; if(u!=source) u = pre[u]; } } return flow; } void initt() { memset(head,-1,sizeof(head)); bnum=0; } int n; void Dijstra(int v0,int t) { FOR(i,0,n) { vis[i] = 0; di[i] = ma[v0][i]; } vis[v0] = 1; di[v0] = 0; FOR(i,1,n) { int u = v0,mi = MAX; FOR(j,0,n) { if(!vis[j] && di[j] < mi) { u = j; mi = di[j]; } } vis[u] = 1; FOR(j,0,n) { if(!vis[j] && ma[u][j] < MAX && di[u] + ma[u][j] < di[j]) { di[j] = ma[u][j] + di[u]; } } } } int main() { int s,t; while(~scanf("%d",&n)) { initt(); FOR(i,0,n) { FOR(j,0,n) { scanf("%d",&ma[i][j]); if(i==j) ma[i][j] = 0; if(ma[i][j]<0) ma[i][j] = MAX; } } scanf("%d%d",&s,&t); if(s==t) { puts("inf");// ----------->坑爹啊。。。 continue; } Dijstra(s,t); int dd = di[t]; //printf("di[t] = %d ",dd); FOR(i,0,n) { FOR(j,0,n) { if(ma[i][j]< MAX && di[i] + ma[i][j] + (dd-di[j]) == dd ) { add(i,j,1); } } } int ans = ISAP(s,t,n+1); cout<<ans<<endl; } return 0; }