HNU校内训练 Skeletons Tehran 2016 反向建边

抱歉没时间仔细讲解

,先mark一下,以后再更。

S

keletons

Time Limit: 10000ms, Special Time Limit:25000ms, Memory Limit:524288KB
Total submit users: 6, Accepted users: 1
Problem 14126 : No special judgement
Problem description

You have recently started your clan in the game of Trash of Clans. Each clan has several villages, and some one-directional roads each connecting two (not necessarily different) villages. Assume that all the roads have the same length. You can produce troops in your clan, and then attack another clan. Your favourite troops are wall breakers ? the skeletons that carry bombs, run and break walls of the enemy villages. The skeletons, like other troops in Trash of Clans, are smart and unpredictable.

During an attack you select the enemy clan, put one skeleton in every village of the enemy, choose a real positive value t for the bomb timers, and press the Attack key. Immediately, every skeleton randomly selects an arbitrary enemy village as the target such that each enemy village is the target of exactly one skeleton. Note that the starting and target village of a skeleton may be identical. All skeletons run at a constant and equal speed during the attack, without stop. They pass the roads in the correct direction and might pass a road several times. After exactly t seconds, a big bang happens and all skeletons explode.

An attack is successful if all skeletons can blow up their targets. The skeletons are so smart and each of them will choose a route to guarantee it will be at the target village exactly after t seconds, if such a route exists. Given a list of clans, your task is to determine the clans for which you can choose a timer value in order to guarantee the success of the attack. 

 
Input
There are multiple clan descriptions in the input. For each clan, the first line contains the number of villages n (1 ≤ n ≤ 50,000) and the number of roads m (1 ≤ m ≤ 100,000). The villages are numbered 1 through n. Each of the next m lines consists of two space-separated integers x and y denoting a one-directional road from village x to village y. There might be multiple roads connecting two villages, or some roads with identical start and end villages. The input terminates with a line containing 0 0 which should not be processed.

 
Output
For each clan write either the character “Y” denoting that you can choose a timer value t guaranteeing the success of every attack, or “N” otherwise.

 
Sample Input
9 10
1 2
2 3
3 4
4 5
5 1
4 6
6 7
7 8
8 9
9 3
3 3
1 2
2 3
1 3
0 0
Sample Output
Y
N
Problem Source
Tehran 2016
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<iomanip>
#include<cmath>
using namespace std;
const int maxn = 5e4+5;
struct node{
    int u,to;
}edge[maxn<<1][2];
int head[maxn][2], tail[maxn][2], dep[maxn][2], n, m, vis[maxn][2], cnt;

void add(int x, int y){
    cnt++;
    if (head[x][0]<0){
        head[x][0]=cnt;
    }
    edge[tail[x][0]][0].to=cnt;    edge[cnt][0].u=y;  edge[cnt][0].to=-1;    tail[x][0]=cnt;
    if (head[y][1]<0){
        head[y][1]=cnt;
    }
    edge[tail[y][1]][1].to=cnt;    edge[cnt][1].u=x;  edge[cnt][1].to=-1;    tail[y][1]=cnt;
    return ;
}

void dfs(int u, int zf){
    int k;
    for (int i=head[u][zf];i>0;i=edge[i][zf].to){
        k=edge[i][zf].u;
        if (k>0&&vis[k][zf]){
            vis[k][zf]=false;   dep[k][zf]=dep[u][zf]+1;
            dfs(k,zf);
        }
    }
    return ;
}

void read(){
    memset(dep,-1,sizeof(dep)); memset(tail,-1,sizeof(tail));   memset(head,-1,sizeof(head));   memset(vis,true,sizeof(vis));
    int j,k;
    cnt=0;
    for (int i=1;i<=m;++i){
        scanf("%d%d",&j,&k);
        add(j,k);
    }
    return ;
}
bool solve(){
    vis[1][0]=false;   vis[1][1]=false;
    dep[1][0]=dep[1][1]=1;
    dfs(1,0);   dfs(1,1);
    for (int i=1;i<=n;++i){
        if (dep[i][0]<0||dep[i][1]<0){
            return false;
        }
    }
    int ans=0;
    for (int i=1;i<=m;++i){
        ans=__gcd(ans,dep[edge[i][0].u][1]+dep[edge[i][1].u][0]-1);
    }
    if (ans==1){
        return true;
    }else{
        return false;
    }
}
int main(){
    while(~scanf("%d%d",&n,&m)){
        if (n==0){
            break;
        }
        read();
        if (solve()){
            puts("Y");
        }else{
            puts("N");
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值