zoukankan      html  css  js  c++  java
  • SPOJ 962 Intergalactic Map

    Intergalactic Map

    Time Limit: 6000ms
    Memory Limit: 262144KB
    This problem will be judged on SPOJ. Original ID: IM
    64-bit integer IO format: %lld      Java class name: Main
     

    Jedi knights, Qui-Gon Jinn and his young apprentice Obi-Wan Kenobi, are entrusted by Queen Padmé Amidala to save Naboofrom an invasion by the Trade Federation. They must leave Naboo immediately and go to Tatooine to pick up the proof of the Federation’s evil design. They then must proceed on to the Republic’s capital planet Coruscant to produce it in front of the Republic’s Senate. To help them in this endeavor, the queen’s captain provides them with an intergalactic map. This map shows connections between planets not yet blockaded by the Trade Federation. Any pair of planets has at most one connection between them, and all the connections are two-way. To avoid detection by enemy spies, the knights must embark on this adventure without visiting any planet more than once. Can you help them by determining if such a path exists? 

    Note - In the attached map, the desired path is shown in bold.

    Input Description

    The first line of the input is a positive integer t ≤ 20, which is the number of test cases. The descriptions of the test cases follow one after the other. The first line of each test case is a pair of positive integers n, m (separated by a single space). 2 ≤ n ≤ 30011 is the number of planets and m ≤ 50011 is the number of connections between planets. The planets are indexed with integers from 1 to n. The indices of Naboo, Tatooine and Coruscant are 1, 2, 3 respectively. The next m lines contain two integers each, giving pairs of planets that have a connection between them.

    Output Description

    The output should contain t lines. The ith line corresponds to the ith test case. The output for each test case should be YES if the required path exists and NO otherwise.

    Example


    Input
    2
    3 3
    1 2
    2 3
    1 3
    3 1
    1 3

    Output
    YES
    NO

     

    Source

     
    解题:不错的无向图拆点最大流。
     
    由于要求每个点只通过一次,可以把点约束转化为边约束。边流量为1就是了。
     
    很有意思的地方啊,S是与2‘相连,而不是2相连。原因嘛!在这道题目,我们需要从1到2再到3,不重复经过点。现在化成边了,也就是不重复经过边。很明显,从2进行两次增广,第一次到1,第二次到3.两次增广都造访了2号顶点,也就是如果S直接与2相连,由于2号点的约束,导致2号点只能造访一次,也就是2-2’这条边,所有只能增广一次。将S与2‘相连,就能进行多次增广了。
     
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <algorithm>
     6 #include <climits>
     7 #include <vector>
     8 #include <queue>
     9 #include <cstdlib>
    10 #include <string>
    11 #include <set>
    12 #include <stack>
    13 #define LL long long
    14 #define pii pair<int,int>
    15 #define INF 0x3f3f3f3f
    16 using namespace std;
    17 const int maxn = 200000;
    18 struct arc{
    19     int to,flow,next;
    20     arc(int x = 0,int y = 0,int z = -1){
    21         to = x;
    22         flow = y;
    23         next = z;
    24     }
    25 };
    26 arc e[maxn*10];
    27 int head[maxn],d[maxn],cur[maxn];
    28 int tot,S,T,n,m;
    29 void add(int u,int v,int flow){
    30     e[tot] = arc(v,flow,head[u]);
    31     head[u] = tot++;
    32     e[tot] = arc(u,0,head[v]);
    33     head[v] = tot++;
    34 }
    35 int q[maxn],hd,tl;
    36 bool bfs(){
    37     hd = tl = 0;
    38     memset(d,-1,sizeof(d));
    39     q[tl++] = S;
    40     d[S] = 1;
    41     while(hd < tl){
    42         int u = q[hd++];
    43         for(int i = head[u]; ~i; i = e[i].next){
    44             if(e[i].flow && d[e[i].to] == -1){
    45                 d[e[i].to] = d[u] + 1;
    46                 q[tl++] = e[i].to;
    47             }
    48         }
    49     }
    50     return d[T] > -1;
    51 }
    52 int dfs(int u,int low){
    53     if(u == T) return low;
    54     int tmp = 0,a;
    55     for(int &i = cur[u]; ~i; i = e[i].next){
    56         if(e[i].flow && d[e[i].to] == d[u]+1&&(a=dfs(e[i].to,min(e[i].flow,low)))){
    57             e[i].flow -= a;
    58             e[i^1].flow += a;
    59             tmp += a;
    60             low -= a;
    61             if(!low) break;
    62         }
    63     }
    64     if(!tmp) d[u] = -1;
    65     return tmp;
    66 }
    67 int dinic(){
    68     int ans = 0;
    69     while(bfs()){
    70         memcpy(cur,head,sizeof(head));
    71         ans += dfs(S,INF);
    72     }
    73     return ans;
    74 }
    75 int main() {
    76     int cs,u,v;
    77     scanf("%d",&cs);
    78     while(cs--){
    79         scanf("%d %d",&n,&m);
    80         memset(head,-1,sizeof(head));
    81         S = tot = 0;
    82         T = n<<1|1;
    83         for(int i = 0; i < m; ++i){
    84             scanf("%d %d",&u,&v);
    85             if(u > n || v > n) continue;
    86             add(u+n,v,1);
    87             add(v+n,u,1);
    88         }
    89         for(int i = 1; i <= n; ++i) add(i,i+n,1);
    90         add(1+n,T,1);
    91         add(3+n,T,1);
    92         add(S,2+n,2);//注意细节啊
    93         printf("%s
    ",dinic() == 2?"YES":"NO");
    94     }
    95     return 0;
    96 }
    View Code
  • 相关阅读:
    java中分页对象类
    java日期处理类DateUtil
    java日期处理类DateUtil
    Java Socket编程
    MySQL中TIMESTAMPDIFF和TIMESTAMPADD函数的用法
    java中用SAX方式解析xml文件
    First Demo
    软件测试面试/笔试题题库(知识的搬运工,不谢!)
    2017年 6月29 开始博客园之旅--愿自己变得更强大!
    DUIEngine使用Visual Studio 2010编译Debug_Dll版有关Error MSB3073错误解决方案
  • 原文地址:https://www.cnblogs.com/crackpotisback/p/4084141.html
Copyright © 2011-2022 走看看