您的位置:首页 > 其它

HDU 3416 Marriage Match IV

2013-10-27 20:10 316 查看
题意:给出一张n个点m条边的无向图( 2<=n<=1000, 0<=m<=100000 )和起点S、终点T。现在要求你每次从S出发都使用一条最短路到达T,并且每条路只能走一次。问最多可以从S走到T走几次最短路。

先处理出S到所有点的最短路,假设S到点i的最短路为d[i]。枚举每条边(from,to,cost),如果d[to]=d[from]+cost,在新图中加一条边(from,to,1),完了之后从S到T跑最大流。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define INF 1<<30
#define maxn 1010
#define maxm 300000
using namespace std;
typedef pair<int,int> pii;
int v[maxm],next[maxm],w[maxm];
int first[maxn],d[maxn],work[maxn],q[maxn];
int e,S,T,N,M;
struct Edge{
int from,to,dist;
}edge[100010];

void init(){
e = 0;
memset(first,-1,sizeof(first));
}

void add_edge1(int a,int b,int c){
v[e] = b;next[e] = first[a];w[e] = c;first[a] = e++;
}

void add_edge2(int a,int b,int c){
//printf("add:%d to %d,cap = %d\n",a,b,c);
v[e] = b;next[e] = first[a];w[e] = c;first[a] = e++;
v[e] = a;next[e] = first[b];w[e] = 0;first[b] = e++;
}

void dijkstra(int src){
priority_queue <pii,vector<pii>,greater<pii> > q;
memset(d,-1,sizeof(d));
d[src] = 0;
q.push(make_pair(0,src));
while(!q.empty()){
while(!q.empty() && q.top().first > d[q.top().second])  q.pop();
if(q.empty())   break;
int u = q.top().second;
q.pop();
for(int i = first[u];i != -1;i = next[i]){
if(d[v[i]] > d[u] + w[i] || d[v[i]] == -1){
d[v[i]] = d[u] + w[i];
q.push(make_pair(d[v[i]],v[i]));
}
}
}
}

int bfs(){
int rear = 0;
memset(d,-1,sizeof(d));
d[S] = 0;q[rear++] = S;
for(int i = 0;i < rear;i++){
for(int j = first[q[i]];j != -1;j = next[j])
if(w[j] && d[v[j]] == -1){
d[v[j]] = d[q[i]] + 1;
q[rear++] = v[j];
if(v[j] == T)   return 1;
}
}
return 0;
}

int dfs(int cur,int a){
if(cur == T)    return a;
for(int &i = work[cur];i != -1;i = next[i]){
if(w[i] && d[v[i]] == d[cur] + 1)
if(int t = dfs(v[i],min(a,w[i]))){
w[i] -= t;w[i^1] += t;
return t;
}
}
return 0;
}

int dinic(){
int ans = 0;
while(bfs()){
memcpy(work,first,sizeof(first));
while(int t = dfs(S,INF))   ans += t;
}
return ans;
}

int main()
{
int kase;
scanf("%d",&kase);
while(kase--){
init();
scanf("%d%d",&N,&M);
for(int i = 0;i < M;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add_edge1(a,b,c);
edge[i].from = a;
edge[i].to = b;
edge[i].dist = c;
}
scanf("%d%d",&S,&T);
dijkstra(S);
//for(int i = 1;i <= N;i++)
//    printf("d[%d] = %d\n",i,d[i]);
init();
for(int i = 0;i < M;i++){
int from = edge[i].from;
int to = edge[i].to;
int dist = edge[i].dist;
if(d[to] == d[from] + dist)
add_edge2(from,to,1);
}
int ans = dinic();
printf("%d\n",ans);
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: