天天看點

SPOJ IM 962 網絡流最大流 解題報告

M - Intergalactic Map

Map Jedi knights, Qui-Gon Jinn and his young apprentice Obi-Wan Kenobi, are entrusted by Queen Padmé Amidala to save Naboo from 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

【解題報告】

【題目大意】

在一個無向圖中,一個人要從A點趕往B點,之後再趕往C點,且要求中途不能多次經過同一個點。問是否存在這樣的路線。(3 <= N <= 30011, 1 <= M <= 50011)

【模組化方法】

由于每個點隻能走一次,似乎最短路之類的算法不能用,隻有往網絡流上靠。将每個點i拆成兩個點i’, i’’并加邊(i’, i’’, 1)就能輕易達到這個目的。起初我一直以A為源點思考,卻怎麼也想不出如何處理先後經過兩個彙點的問題,直到靈光一現,想到可以以B為源點,A、C為彙點。

代碼如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define N 30020
#define M 50020
#define inf 0x3f3f3f3f

int cnt,head[N],dis[N],vis[N];
struct Edge{int to,nxt,f;}e[M<<];
int t,n,m,ss,tt;

void adde(int u,int v,int c)
{
    e[++cnt].to=v;e[cnt].f=c;
    e[cnt].nxt=head[u];head[u]=cnt;
    e[++cnt].to=u;e[cnt].f=;
    e[cnt].nxt=head[v];head[v]=cnt;
}
bool bfs()
{
    memset(dis,,sizeof(dis));
    memset(vis,,sizeof(vis));
    queue <int> q;
    vis[ss]=;q.push(ss);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        for(int i=head[u];~i;i=e[i].nxt)
        {
            int v=e[i].to;
            if(e[i].f&&!vis[v])
            {
                q.push(v);vis[v]=;
                dis[v]=dis[u]+;
            }
        }
    }
    return vis[tt];
}
int dfs(int u,int delta)
{
    if(u==tt) return delta;
    int ret=;
    for(int i=head[u];delta&&~i;i=e[i].nxt)
    {
        int v=e[i].to;
        if(e[i].f&&dis[v]==dis[u]+)
        {
            int flow=dfs(v,min(e[i].f,delta));
            e[i].f-=flow;
            e[i^].f+=flow;
            delta-=flow;
            ret+=flow;
        }
    }
    return ret;
}
int Dinic()
{
    int ret=;
    while(bfs()) ret+=dfs(ss,inf);
    return ret;
}
int main()
{
    for(scanf("%d",&t);t;--t)
    {
        cnt=-;
        memset(head,-,sizeof(head));
        scanf("%d%d",&n,&m);
        ss=,tt=n*+;
        adde(ss,+n,);
        adde(,tt,);
        adde(,tt,);
        for(int i=;i<=n;++i) adde(i,i+n,);
        for(int i=,u,v;i<=m;++i)  
        {  
            scanf("%d%d",&u,&v);  
            if(u<||u>n||v<||v>n) continue;  
            adde(u+n,v,);adde(v+n,u,);  
        }     
        puts(Dinic()==?"YES":"NO");
    }
    return ;
}
           

繼續閱讀