UVa10806

来源:互联网 发布:网络监控摄像头序列号 编辑:程序博客网 时间:2024/06/06 01:37

题目链接

简介:
给出一个有n个节点,m条边的带权无向图,找到起点S到终点T的最短往返路线不能重复走同一条边

简介:
这道题很像dijkstra求最短路和次短路
但是求解最短路次短路的时候,我们贯彻的是一种贪心思想,并且可以走重边
如果只是简单地把最短路上的边删除,再跑一边最短路,是会出错的
因此这道题就带有一点dp的味道了

既像贪心,又像dp:网络流

这道题的建图很简单,
因为我们要找出最短的两条互不影响的路,所以我们用费用流解决
这样就可以保证找到的一定是全脂和最小的路径

但如果从S到T用多条路怎么办
很简单,我们限制一下流量就好了
设超级源点SS,向S连边,容量为2,费用为0
设超级汇点TT,T向其连边,容量为2,费用为0

只有增广出来的总流量为2时,原问题才有解

//这里写代码片#include<cstdio>#include<cstring>#include<iostream>#include<queue>using namespace std;const int INF=0x33333333;const int N=102;struct node{    int x,y,v,c,nxt;};node way[N*N*2];int st[N],tot,n,m,s,t;int pre[N],dis[N],ans;bool in[N];void add(int u,int w,int z,int cc){    tot++;    way[tot].x=u;way[tot].y=w;way[tot].v=z;way[tot].c=cc;way[tot].nxt=st[u];st[u]=tot;    tot++;    way[tot].x=w;way[tot].y=u;way[tot].v=0;way[tot].c=-cc;way[tot].nxt=st[w];st[w]=tot;}int spfa(int s,int t){    memset(pre,0,sizeof(pre));    memset(dis,0x33,sizeof(dis));    memset(in,0,sizeof(in));    queue<int> Q;    Q.push(s);    dis[s]=0;  in[s]=1;    while (!Q.empty())    {        int now=Q.front(); Q.pop();        in[now]=0;        for (int i=st[now];i!=-1;i=way[i].nxt)            if (way[i].v&&dis[way[i].y]>dis[now]+way[i].c)            {                dis[way[i].y]=dis[now]+way[i].c;                pre[way[i].y]=i;                if (!in[way[i].y])                {                    in[way[i].y]=1;                    Q.push(way[i].y);                }            }    }    return dis[t]<INF;}int doit(int s,int t){    ans=0;    int flow=0;    while (spfa(s,t))    {        int sum=INF;        for (int i=t;i!=s;i=way[pre[i]].x)             sum=min(sum,way[pre[i]].v);        ans+=sum*dis[t]; flow+=sum;        for (int i=t;i!=s;i=way[pre[i]].x)            way[pre[i]].v-=sum,            way[pre[i]^1].v+=sum;    }    return flow;}int main(){    while (scanf("%d",&n)!=EOF&&n)    {        memset(st,-1,sizeof(st));        tot=-1;        scanf("%d",&m);        for (int i=1;i<=m;i++)        {            int u,w,z;            scanf("%d%d%d",&u,&w,&z);            add(u,w,1,z);            add(w,u,1,z);        }        s=0; t=n+1;        add(s,1,2,0);        add(n,t,2,0);        int flow=doit(s,t);        if (flow==2) printf("%d\n",ans);        else printf("Back to jail\n");    }    return 0;}
原创粉丝点击