Marriage Match IV HDU

来源:互联网 发布:js去除字符串中的符号 编辑:程序博客网 时间:2024/05/28 15:08

点击打开链接

这个题也是看了题解才想到要用最短路和网络流结合的。。

题目要求每次只能走最短路 意思不是走一次最短路就把这条路径删除 然后再找新的最短路即原图的次短路  而是仍然找一条和最开始的最短路长度一样的路径

这样所有构成最短路的边都是可以确定的

反向建图 dis1[n]代表从起点ss到每个点的最短距离 dis2[n]代表从终点ee到每个点的最短距离 对于一条边edge[i] 如果dis1[edge[i].u]+edge[i].w+dis2[edge[i].v]==dis1[ee] 则这条边就在一条最短路上

最后 把起点作源点 终点作汇点 以所有最短路上的边建立网络流模型(边权值为1) 就可以知道 利用所有的这些边可以凑数几条从源点到汇点的增广路

因为边权值是1 所以每条增广路的流量都是1 最终得到的最大流即是增广路条数

#include <stdio.h>#include <queue>#include <cstring>#include <algorithm>using namespace std;#define N 0x3f3f3f3fstruct nodeI{    int u;    int v;    int w;};struct nodeII{    int v;    int w;    int next;};struct nodeIII{    friend bool operator < (nodeIII n1,nodeIII n2)    {        return n1.w>n2.w;    }    int v;    int w;};priority_queue <nodeIII> que;nodeI gg[100010];nodeII edge1[100010],edge2[100010],edge3[200010];int first1[1010],first2[1010],first3[1010],dis1[1010],dis2[1010],book[1010];int dis[1010],gap[1010],cur[1010],pre[1010];int n,m,num,ss,ee,ans;void addedge(int u,int v,int w,nodeII* edge,int* first){    edge[num].v=v;    edge[num].w=w;    edge[num].next=first[u];    first[u]=num++;    return;}void calculate(nodeII* edge,int* first,int* dis,int &s){    nodeIII cur,tem;    int i,u,v,w;    while(!que.empty()) que.pop();    for(i=1;i<=n;i++)    {        dis[i]=N;        book[i]=0;    }    tem.v=s,tem.w=0;    que.push(tem);    dis[s]=0;    while(!que.empty())    {        cur=que.top();        que.pop();        u=cur.v;        if(book[u]==1) continue;        book[u]=1;        for(i=first[u];i!=-1;i=edge[i].next)        {            v=edge[i].v,w=edge[i].w;            if(book[v]==0&&dis[v]>dis[u]+w)            {                dis[v]=dis[u]+w;                tem.v=v,tem.w=dis[v];                que.push(tem);            }        }    }    return;}void judge(){    int i,u,v,w;    memset(first3,-1,sizeof(first3));    num=0;    for(i=1;i<=m;i++)    {        u=gg[i].u,v=gg[i].v,w=gg[i].w;        if(dis1[u]+w+dis2[v]==dis1[ee])        {            addedge(u,v,1,edge3,first3);            addedge(v,u,0,edge3,first3);        }    }    return;}void bfs(){    queue <int> que;    int i,u,v;    memset(dis,-1,sizeof(dis));    memset(gap,0,sizeof(gap));    que.push(ee);    dis[ee]=0;    while(!que.empty())    {        u=que.front();        que.pop();        gap[dis[u]]++;        for(i=first3[u];i!=-1;i=edge3[i].next)        {            v=edge3[i].v;            if(dis[v]==-1)            {                que.push(v);                dis[v]=dis[u]+1;            }        }    }    return;}void isap(){    int j,u,v,w,flow,minn;    bfs();    memcpy(cur,first3,sizeof(first3));    memset(pre,-1,sizeof(pre));    ans=0,u=ss,flow=N;    while(dis[ss]<n)    {        int &i=cur[u];        for(;i!=-1;i=edge3[i].next)        {            v=edge3[i].v,w=edge3[i].w;            if(dis[v]+1==dis[u]&&w>0)            {                pre[v]=i;                u=v,flow=min(flow,w);                if(u==ee)                {                    while(u!=ss)                    {                        j=pre[u];                        edge3[j].w-=flow;                        edge3[j^1].w+=flow;                        u=edge3[j^1].v;                    }                    ans+=flow,flow=N;                }                break;            }        }        if(i==-1)        {            if(--gap[dis[u]]==0) break;            cur[u]=first3[u];            minn=n-1;            for(j=first3[u];j!=-1;j=edge3[j].next)            {                v=edge3[j].v,w=edge3[j].w;                if(w>0)                {                    minn=min(minn,dis[v]);                }            }            dis[u]=minn+1;            gap[dis[u]]++;            if(u!=ss)            {                u=edge3[pre[u]^1].v;            }        }    }    return;}int main(){    int t,i;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&m);        for(i=1;i<=m;i++)        {            scanf("%d%d%d",&gg[i].u,&gg[i].v,&gg[i].w);        }        scanf("%d%d",&ss,&ee);        memset(first1,-1,sizeof(first1));        num=0;        for(i=1;i<=m;i++)        {            addedge(gg[i].u,gg[i].v,gg[i].w,edge1,first1);        }        calculate(edge1,first1,dis1,ss);        memset(first2,-1,sizeof(first2));        num=0;        for(i=1;i<=m;i++)        {            addedge(gg[i].v,gg[i].u,gg[i].w,edge2,first2);        }        calculate(edge2,first2,dis2,ee);        judge();        isap();        printf("%d\n",ans);    }    return 0;}

原创粉丝点击