HDU — 3416 Marriage Match IV(最大流+最短路)

来源:互联网 发布:打开数据漫游会收费没 编辑:程序博客网 时间:2024/06/05 11:15

题目大意:

有n个城市,m条道路,给出起点,终点,求从起点到终点一共有多少条不同的最短路径;

思路分析:

先用最短路求出最短路径,在此基础上建边,权值为1(表示一条边只能走一遍),跑一边最大流即可;

注意源点和汇点不一定就是1和n这两个点;

代码实现:

#include<cstdio>#include<cstring>#include<queue>#include<vector>#include<iostream>#define Max(a,b) ((a)>(b)?(a):(b))#define Min(a,b) ((a)<(b)?(a):(b))using namespace std;const int N=1010;const int M=200010;const int INF=0x3f3f3f3f;int n,m,s,t,top,head[N],gap[N],cur[N],dis[N],d[N],vis[N],pre[N];struct Edge{    int to,next,flow;}edge[M];struct E{    int to,val;    E(int _to=0,int _val=0):to(_to),val(_val){}};vector<E> v[N];void Addedge(int from,int to,int val){    edge[top].to=to,edge[top].next=head[from],edge[top].flow=val,head[from]=top++;    edge[top].to=from,edge[top].next=head[to],edge[top].flow=0,head[to]=top++;}void Spfa(){    queue<int> q;    memset(vis,0,sizeof(vis));    memset(d,0x3f,sizeof(d));    q.push(s);    d[s]=0;    while(!q.empty()){        int u=q.front();        q.pop();        vis[u]=0;        for(int i=0;i<v[u].size();++i){            int tmp=v[u][i].to;            if(d[tmp]>d[u]+v[u][i].val){                d[tmp]=d[u]+v[u][i].val;                if(!vis[tmp]){                    vis[tmp]=1;                    q.push(tmp);                }            }        }    }}void Bfs(){    queue<int> q;    memset(gap,0,sizeof(gap));    memset(dis,-1,sizeof(dis));    gap[0]=1,dis[t]=0;    q.push(t);    while(!q.empty()){        int u=q.front();        q.pop();        for(int i=head[u];i+1;i=edge[i].next){            if(dis[edge[i].to]==-1){                dis[edge[i].to]=dis[u]+1;                gap[dis[edge[i].to]]++;                q.push(edge[i].to);            }        }    }}int Sap(){    Bfs();    memset(pre,-1,sizeof(pre));    for(int i=1;i<=n;++i) cur[i]=head[i];    int u=s,i,cur_flow,max_flow=0,neck,tmp;    while(dis[s]<n){        if(u==t){            cur_flow=INF;            for(int i=s;i!=t;i=edge[cur[i]].to){                if(cur_flow>edge[cur[i]].flow){                    neck=i;                    cur_flow=edge[cur[i]].flow;                }            }            for(int i=s;i!=t;i=edge[cur[i]].to){                tmp=cur[i];                edge[tmp].flow-=cur_flow;                edge[tmp^1].flow+=cur_flow;            }            max_flow+=cur_flow;            u=neck;        }        int i;        for(i=cur[u];i!=-1;i=edge[i].next)            if(edge[i].flow&&dis[u]==dis[edge[i].to]+1) break;        if(i!=-1){            cur[u]=i;            pre[edge[i].to]=u;            u=edge[i].to;        }else{            if(--gap[dis[u]]==0) break;            cur[u]=head[u];            int mindis=n;            for(i=head[u];i!=-1;i=edge[i].next){                if(edge[i].flow&&mindis>dis[edge[i].to])                    mindis=dis[edge[i].to];            }            dis[u]=mindis+1;            gap[dis[u]]++;            if(u!=s) u=pre[u];        }    }    return max_flow;}int main(){    int T,v1,v2,va;    scanf("%d",&T);    while(T--){        scanf("%d%d",&n,&m);        memset(head,-1,sizeof(head));        for(int i=1;i<=n;++i) v[i].clear();        top=0;        for(int i=0;i<m;++i){            scanf("%d%d%d",&v1,&v2,&va);            if(v1==v2) continue;            v[v1].push_back(E(v2,va));        }        scanf("%d%d",&s,&t);        Spfa();        for(int i=1;i<=n;++i)            for(int j=0;j<v[i].size();++j)                if(d[v[i][j].to]==d[i]+v[i][j].val) Addedge(i,v[i][j].to,1);        int res=Sap();        printf("%d\n",res);    }}


0 0
原创粉丝点击