hdu 3416 最短路+最大流

来源:互联网 发布:中国同性题材网络剧 编辑:程序博客网 时间:2024/06/05 23:42
题意: 有 n 个城市,知道了起点和终点,

有 m 条有向边,问从起点到终点不相交的最短路一共有多少条。

法:

      先dijstra(st),再dijstra(ed)一遍如果存在dist[u]+disd[v]+Edg[u].w==dis[ed] 那么将这条边加入网络中,最后求最大流即可!!

/*题意: 有 n 个城市,知道了起点和终点,有 m 条有向边,问从起点到终点不相交的最短路一共有多少条。*/#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <algorithm>#include <set>#include <map>#include <vector>#include <queue>#include <ctime>using namespace std;const int N=2002;const int M = 222222;const int INF = 1 << 30;int n,m,t,dis[N];int vis[N],head[N],Head[N],cnt;int gap[N],pre[N],cur[N];int NE,NV,sink,source,Edgeu[M],Edgev[M],Edgew[M];struct node{    int v,next,w;    bool operator < (const node &a) const    {        return w > a.w;    }} Edge[M*4],t1,t2;struct Node{    int c,pos,next;} E[M*4];void addedge(int u,int v,int w){    Edge[cnt].v = v;    Edge[cnt].next = Head[u];    Edge[cnt].w = w;    Head[u] = cnt++;}void addEdge(int u,int v,int c){    E[NE].c = c;    E[NE].pos = v;    E[NE].next = head[u];    head[u] = NE++;    E[NE].c = 0;    E[NE].pos = u;    E[NE].next = head[v];    head[v] = NE++;}#define FF(i,NV) for(int i=0;i<NV;i++)int sap(int s,int t){    memset(dis,0,sizeof(int)*(NV+1));    memset(gap,0,sizeof(int)*(NV+1));    memset(pre,-1,sizeof(int)*(NV+1));    FF(i,NV) cur[i] = head[i];    int u = pre[s] = s,maxflow = 0,aug =INF;    gap[0] = NV;    while(dis[s] < NV)    {loop:        for(int &i = cur[u]; i != -1; i = E[i].next)        {            int v = E[i].pos;            if(E[i].c && dis[u] == dis[v] + 1)            {                aug=min(aug,E[i].c);                pre[v] = u;                u = v;                if(v == t)                {                    maxflow += aug;                    for(u = pre[u]; v != s; v = u,u = pre[u])                    {                        E[cur[u]].c -= aug;                        E[cur[u]^1].c += aug;                    }                    aug =INF;                }                goto loop;            }        }        if( (--gap[dis[u]]) == 0)   break;        int mindis = INF;        for(int i = head[u]; i != -1 ; i = E[i].next)        {            int v = E[i].pos;            if(E[i].c && mindis > dis[v])            {                cur[u] = i;                mindis = dis[v];            }        }        gap[ dis[u] = mindis+1 ] ++;        u = pre[u];    }    return maxflow;}void dijstra(int  st,int dis[]){    priority_queue<node> q;    while(!q.empty()) q.top(),q.pop();    for(int i = Head[st] ; i != -1 ; i = Edge[i].next)    {        int v = Edge[i].v;        if(Edge[i].w<dis[v])        {            dis[v] = Edge[i].w;            t1.w = dis[v];            t1.v =  v;            q.push(t1);        }    }    dis[st]=0;//此句没加错了2次,囧~~~    vis[st] = 1;    while(!q.empty())    {        t1 = q.top();        q.pop();        int u = t1.v;        if(vis[u]) continue;        vis[u] = 1;        for(int i = Head[u]; i != -1; i = Edge[i].next)        {            int v = Edge[i].v;            if(!vis[v] && dis[v]>dis[u]+Edge[i].w)            {                dis[v] =dis[u]+Edge[i].w;                t2.v = v;                t2.w = dis[v];                q.push(t2);            }        }    }}int main(){    int n,m,st,ed,disd[N],dist[N];    //freopen("//media/学习/ACM/input.txt","r",stdin);    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&m);        memset(head,-1,sizeof(int)*(n+1));        memset(Head,-1,sizeof(int)*(n+1));        int i,j,u,v,w,num=0;        for(NE=cnt=0,NV=n+2,j=1; j<=m; j++)        {            scanf("%d%d%d",&u,&v,&w);            if(u!=v)            {              addedge(v,u,w);              Edgeu[num]=u,Edgev[num]=v,Edgew[num]=w;              num++;             // addedge(v,u,w);            }        }        scanf("%d%d",&st,&ed);        for(cnt=i=0;i<=n+1;i++) disd[i]=dist[i] = INF;        memset(vis,0,sizeof(int)*(n+1));  dijstra(ed,disd);        memset(Head,-1,sizeof(int)*(n+1));        for(i=0;i<num;i++) addedge(Edgeu[i],Edgev[i],Edgew[i]);        memset(vis,0,sizeof(int)*(n+1));  dijstra(st,dist);        for(i=1;i<=n;i++)        {            for(j=Head[i];j!=-1;j=Edge[j].next)            {                v=Edge[j].v;                if(dist[i]+disd[v]+Edge[j].w==dist[ed])                addEdge(i,v,1);            }        }        if(dist[ed]>=INF)puts("0");        else        printf("%d\n",sap(st,ed));    }    return 0;}


原创粉丝点击