zoukankan      html  css  js  c++  java
  • SGU 185 Two shortest 最短路+最大流

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=21068

    Yesterday Vasya and Petya quarreled badly, and now they don't want to see each other on their way to school. The problem is that they live in one and the same house, leave the house at the same time and go at the same speed by the shortest road. Neither of them wants to change their principles, that is why they want to find two separate shortest routes, which won't make them go along one road, but still they can meet at any junction. They ask you to help them. They number all the junctions with numbers from 1 to N (home and school are also considered as junctions). So their house has the number 1 and the school has the number N, each road connects two junctions exactly, and there cannot be several roads between any two junctions.

    题意描述:有n个节点,找出1~n的两条不相交的最短路(两条路径可以共点不能共边)。

    算法分析:用spfa求出点1到各个点的最短路径,然后再if(d[j]==d[i]+dis[i][j]) 来判断边dis[i][j]是否是在最短路径上,如果是就加到图里,结果就得到以1为顶点的最短路径树,1到树中任意一点的连线都是最短路径,首先把这些边加到网络流的边集中,容量为1。跑一遍1到n的最大流,如果流量>=2则有解,再从原点深搜路径即可。

    说明:这道题很卡内存和时间,MLE!MLE!MLE!M出翔了。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cstdlib>
      5 #include<cmath>
      6 #include<algorithm>
      7 #include<queue>
      8 #include<vector>
      9 #define inf 10737418
     10 using namespace std;
     11 typedef long long ll;
     12 const int maxn=400+10;
     13 const int M = 120000+10;
     14 
     15 int n,m,from,to;
     16 struct Edge
     17 {
     18     int to,cap;
     19     int next;
     20 }edge[M*2];
     21 int head[maxn],edgenum;
     22 
     23 void add(int u,int v,int cap)
     24 {
     25     Edge E={v,cap,head[u]};
     26     edge[edgenum]=E;
     27     head[u]=edgenum++;
     28 
     29     Edge E2={u,0,head[v]};
     30     edge[edgenum]=E2;
     31     head[v]=edgenum++;
     32 }
     33 
     34 int d[maxn];
     35 bool BFS()
     36 {
     37     memset(d,-1,sizeof(d));
     38     d[from]=0;
     39     queue<int> Q;
     40     Q.push(from);
     41     while (!Q.empty() ){
     42         int u=Q.front(); Q.pop();
     43         for (int i=head[u] ;i!=-1 ;i=edge[i].next)
     44         {
     45             int v=edge[i].to;
     46             if (d[v]==-1 && edge[i].cap)
     47             {
     48                 d[v]=d[u]+1,Q.push(v);
     49                 if (d[to] != -1) return true;
     50             }
     51         }
     52     }
     53     return false;
     54 }
     55 int Stack[maxn], top, cur[maxn];
     56 int Dinic(){
     57     int ans=0;
     58     while(BFS())
     59     {
     60         memcpy(cur, head, sizeof(head));
     61         int u = from;      top = 0;
     62         while(1)
     63         {
     64             if(u == to)
     65             {
     66                 int flow = inf, loc;//loc 表示 Stack 中 cap 最小的边
     67                 for(int i = 0; i < top; i++)
     68                     if(flow > edge[ Stack[i] ].cap)
     69                     {
     70                         flow = edge[Stack[i]].cap;
     71                         loc = i;
     72                     }
     73 
     74                     for(int i = 0; i < top; i++)
     75                     {
     76                         edge[ Stack[i] ].cap -= flow;
     77                         edge[Stack[i]^1].cap += flow;
     78                     }
     79                     ans += flow;
     80                     top = loc;
     81                     u = edge[Stack[top]^1].to;
     82             }
     83             for(int i = cur[u]; i!=-1; cur[u] = i = edge[i].next)//cur[u] 表示u所在能增广的边的下标
     84                 if(edge[i].cap && (d[u] + 1 == d[ edge[i].to ]))break;
     85             if(cur[u] != -1)
     86             {
     87                 Stack[top++] = cur[u];
     88                 u = edge[ cur[u] ].to;
     89             }
     90             else
     91             {
     92                 if( top == 0 )break;
     93                 d[u] = -1;
     94                 u = edge[ Stack[--top]^1 ].to;
     95             }
     96         }
     97     }
     98     return ans;
     99 }
    100 int dis[maxn][maxn];
    101 int vis[maxn];
    102 void spfa()
    103 {
    104     for (int i=1 ;i<=n ;i++) d[i]=inf;
    105     d[1]=0;
    106     memset(vis,0,sizeof(vis));
    107     queue<int> Q;
    108     Q.push(1);
    109     vis[1]=1;
    110     while (!Q.empty())
    111     {
    112         int u=Q.front() ;Q.pop() ;
    113         vis[u]=0;
    114         for (int v=1 ;v<=n ;v++)
    115         {
    116             if (d[v]>d[u]+dis[u][v])
    117             {
    118                 d[v]=d[u]+dis[u][v];
    119                 if (!vis[v])
    120                 {
    121                     vis[v]=1;
    122                     Q.push(v);
    123                 }
    124             }
    125         }
    126     }
    127 }
    128 void dfs(int u, int fa)
    129 {
    130     if (u == n){printf("%d
    ",u);return ;}
    131     else printf("%d ",u);
    132     for (int i = head[u] ;i!=-1 ;i=edge[i].next)
    133     {
    134         if (edge[i^1].cap != 1 || (i&1)) continue;
    135         int v=edge[i].to;
    136         if (v == fa) continue;
    137         edge[i^1].cap=0;
    138         dfs(v, u);
    139         return;
    140     }
    141 }
    142 
    143 int main()
    144 {
    145     while (scanf("%d%d",&n,&m)!=EOF)
    146     {
    147         memset(head,-1,sizeof(head));
    148         edgenum=0;
    149         int a,b,c;
    150         for (int i=1 ;i<=n ;i++)
    151             for (int j=1 ;j<=n ;j++)
    152                 dis[i][j]=inf;
    153         for (int i=0 ;i<m ;i++)
    154         {
    155             scanf("%d%d%d",&a,&b,&c);
    156             dis[a][b] = dis[b][a] = min(dis[a][b], c);
    157         }
    158         spfa();
    159         if (d[n]==inf) {printf("No solution
    ");continue; }
    160         from=1;
    161         to=n+1;
    162         for (int i=1 ;i<=n ;i++)
    163         {
    164             for (int j=1 ;j<=n ;j++)
    165             {
    166                 if(dis[i][j]!=inf && d[j] == dis[i][j] + d[i])
    167                     add(i,j,1);
    168             }
    169         }
    170         add(n,to,2);
    171         int sum=Dinic();
    172         if (sum<2) {printf("No solution
    ");continue; }
    173         dfs(1,1);
    174         dfs(1,1);
    175     }
    176     return 0;
    177 }
  • 相关阅读:
    ReactNative之从HelloWorld中看环境搭建、组件封装、Props及State
    iOS开发之虾米音乐频道选择切换效果分析与实现
    Cocoa包管理器之Carthage详解及CocoaPods中心化+Carthage的二进制化
    Cocoa包管理器之CocoaPods详解
    Git知识总览(六) Git分支中的远程操作实践
    Git知识总览(五) Git中的merge、rebase、cherry-pick以及交互式rebase
    Git知识总览(四) git分支管理之rebase 以及 cherry-pick相关操作
    Git知识总览(三) 分支的创建、删除、切换、合并以及冲突解决
    Git知识总览(二) git常用命令概览
    Git知识总览(一) 从 git clone 和 git status 谈起
  • 原文地址:https://www.cnblogs.com/huangxf/p/4372984.html
Copyright © 2011-2022 走看看