[kuangbin带你飞]专题五 【并查集】 【--完结--】

来源:互联网 发布:权重轮询调度算法 编辑:程序博客网 时间:2024/05/16 17:37

题目链接:点击打开链接

A - Wireless Network

POJ - 2236                    

AC代码:

#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int maxn = 1005;int n, d;int rep[maxn], x[maxn], y[maxn], f[maxn];void init(){    for(int i = 1; i <= n; ++i)    {        f[i] = i;        rep[i] = 0;    }}int getf(int v){    if(f[v] != v)        f[v] = getf(f[v]);    return f[v];}int dis(int u, int v){    int t1 = x[u] - x[v];    int t2 = y[u] - y[v];    if(t1*t1+t2*t2 <= d*d) return 1;    return 0;}int main(){    char ch;    int tem, tem1, tem2;    int k1, k2;    scanf("%d%d",&n, &d);    init();    for(int i = 1; i <= n; ++i)        scanf("%d%d",&x[i],&y[i]);    while(cin >> ch)    {        if(ch == 'O')        {            scanf("%d",&tem);            rep[tem] = 1;  //该电脑被修好,选择能与它联通的电脑加入集合            for(int i = 1; i <= n; ++i)            {                if(i != tem && rep[i] && dis(tem, i))                {                    k1 = getf(tem);                    k2 = getf(i);                    f[k1] = k2;                }            }        }        if(ch == 'S')        {            scanf("%d%d",&tem1,&tem2);            k1 = getf(tem1);            k2 = getf(tem2);            //cout << k1 << endl;            //cout << k2 << endl;            if(k1 == k2) cout << "SUCCESS" << endl;            else cout << "FAIL" << endl;        }    }    return 0;}


B - The Suspects

POJ - 1611                    

AC代码:

#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int MAX = 30005;int f[MAX], num[MAX];int ran[MAX];//树的高度int n, m;void init(){    for(int i = 0; i < n; ++i)    {        f[i] = i;        num[i] = 1;    }}int getf(int v){    if(f[v] != v)        f[v] = getf(f[v]);    return f[v];}void merg(int u, int v){    int t1 = getf(u);    int t2 = getf(v);    if(t1 == t2) return ;    if(ran[t1] > ran[t2])    {        //向高的树合并        f[t2] = t1;        num[t1] += num[t2];    }    else    {        //树的高度相同时以t2为根进行合并        if(ran[t1] == ran[t2]) ran[t2]++;        f[t1]= t2;        num[t2] += num[t1];    }}int main(){    int t, tem, tem2;    while(scanf("%d%d",&n,&m) && (n||m))    {        init();        memset(ran, 0, sizeof(ran));        while(m--)        {            scanf("%d",&t);            scanf("%d",&tem);            t--;            while(t--)            {                scanf("%d",&tem2);                merg(tem, tem2);            }        }        int ans = getf(0);        cout << num[ans] << endl;    }    return 0;}

C - How Many Tables

HDU - 1213                    

AC代码:

#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int maxn = 1005;int n, m;int f[maxn];void init()  //注意调用函数init()前先给n赋值{    for(int i = 1; i <= n; ++i)        f[i] = i;}int getf(int v){    if(f[v] != v)        f[v] = getf(f[v]);    return f[v];}void merg(int u, int v){    int t1 = getf(u);    int t2 = getf(v);    if(t1 != t2)        f[t1] = t2;}int main(){    int t, ans, a, b;    while(~scanf("%d",&t))    {        while(t--)        {            scanf("%d%d",&n,&m);            init();            ans = 0;            while(m--)            {                scanf("%d%d",&a,&b);                merg(a, b);            }            for(int i = 1; i <= n; ++i)               if(f[i] == i) ans++;            cout << ans << endl;        }    }    return 0;}


D - How Many Answers Are Wrong

HDU - 3038                    

AC代码:

#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int N = 200005;int f[N], sum[N];int n, m;int getf(int v){    if(f[v] == v) return v;    int t = f[v];    f[v] = getf(f[v]);    sum[v] += sum[t];    return f[v];}void merg(int x, int y, int u, int v, int w){    if(x > y)    {        f[y] = x;        sum[y] = sum[u] - sum[v] - w;    }    else    {        f[x] = y;        sum[x] = w + sum[v] - sum[u];    }}void init(){    for(int i = 0; i <= n; ++i)    {        f[i] = i;        sum[i] = 0;    }}int main(){    while(~scanf("%d%d",&n,&m))    {        init();        int u, v, w, ans = 0;        while(m--)        {            scanf("%d%d%d",&u,&v,&w);            u--;            int x = getf(u);            int y = getf(v);            if(x == y && sum[u] != sum[v] + w)                ans++;            else if(x != y)                merg(x, y, u, v, w);        }        cout << ans << endl;    }    return 0;}


E - 食物链

POJ - 1182                    

AC代码:

#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int maxn = 100005;int f[150000];int x[maxn], y[maxn], t[maxn];int n, k;void init(int n){    for(int i = 0; i < n; ++i)        f[i] = i;}int getf(int v){    if(f[v] != v)        f[v] = getf(f[v]);    return f[v];}void merg(int u, int v){    int t1 = getf(u);    int t2 = getf(v);    if(t1 != t2)        f[t1] = t2;}int same(int u, int v){    return getf(u) == getf(v);}int main(){    scanf("%d%d",&n,&k);    memset(x, 0, sizeof(x));    memset(y, 0, sizeof(y));    memset(t, 0, sizeof(t));    for(int i = 0; i < k; ++i)        scanf("%d%d%d",&t[i],&x[i],&y[i]);    init(3 * n);  //元素x,x+n,x+2*n分别表示x-A,x-B,x-C    int ans = 0;    for(int i = 0; i < k; ++i)    {        int tt = t[i];  //物种间的关系        int xx = x[i] - 1;        int yy = y[i] - 1;        if(xx < 0 || xx >= n || yy < 0 || yy >= n)   //假话        {            ans++;            continue;        }        if(tt == 1) //同类        {            if(same(xx, yy+n) || same(xx, yy+2*n))                ans++;            else            {                merg(xx, yy);                merg(xx+n, yy+n);                merg(xx+2*n, yy+2*n);            }        }        else   //捕食        {            if(same(xx, yy) || same(xx, yy+2*n))                ans++;            else            {                merg(xx, yy+n);                merg(xx+n, yy+2*n);                merg(xx+2*n, yy);            }        }    }    cout << ans << endl;    return 0;}

F - True Liars

POJ - 1417                    

※AC代码:
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int MAX = 1000;int f[MAX];int ran[MAX];int sum[2][MAX];int DP[MAX][MAX];int vis[MAX][MAX];void init(){    memset(ran, 0, sizeof(ran));    for(int i = 0; i < MAX; ++i)    {        f[i] = i;        sum[0][i] = 1;        sum[1][i] = 0;    }}int getf(int v){    if(f[v] == v) return v;    int tem = f[v];    f[v] = getf(f[v]);    ran[v] = ran[v] ^ ran[tem];    return f[v];}void merg(int u, int v, int k){    int t1 = getf(u);    int t2 = getf(v);    if(t1 == t2) return ;    f[t2] = t1;    ran[t2] = k ^ ran[u] ^ ran[v];    sum[0][t1] += sum[0^ran[t2]][t2];    sum[1][t1] += sum[1^ran[t2]][t2];}int main(){    int n, p1, p2;    int x, y;    string s;    while(~scanf("%d%d%d",&n,&p1,&p2) && (n||p1||p2))    {        init();        while(n--)        {            scanf("%d%d",&x,&y);            cin >> s;            if(s == "yes")                merg(x, y, 0);            else                merg(x, y, 1);        }        int w1[MAX], w2[MAX], p[MAX];        memset(w1, 0, sizeof(w1));        memset(w2, 0, sizeof(w2));        int cou = 1;        int suma = p1 + p2;        for(int i = 1; i <= suma; ++i)        {            if(i == getf(i))            {                w1[cou] = sum[0][i];                w2[cou] = sum[1][i];                p[cou] = i;                cou++;            }        }        memset(vis, 0, sizeof(vis));        memset(DP, 0, sizeof(DP));        DP[0][0] = 1;        for(int i = 1; i < cou; ++i)        {            for(int t = p1; t >= w1[i]; --t)            {                if(DP[i-1][t-w1[i]])                {                    DP[i][t] += DP[i-1][t-w1[i]];                    vis[i][t] = 0;                }            }            for(int t = p1; t >= w2[i]; --t)            {                if(DP[i-1][t-w2[i]])                {                    DP[i][t] += DP[i-1][t-w2[i]];                    vis[i][t] = 1;                }            }        }        //如果不能取到或者取到的策略不止一种,不能划分        if(DP[cou-1][p1] != 1)            cout << "no" << endl;        else        {            int ans[MAX];            int tot = 0;            cou--;            while(cou > 0)            {                int cur = vis[cou][p1];                int roo = p[cou];                for(int i = 1; i <= suma; ++i)                {                    if(getf(i) == roo && ran[i] == cur)                    ans[tot++] = i;                }                if(!cur)                    p1 -= w1[cou];                else                    p1 -= w2[cou];                cou--;            }            sort(ans, ans + tot);            for(int i = 0; i < tot; ++i)                cout << ans[i] << endl;            cout << "end" << endl;        }    }    return 0;}


G - Supermarket

POJ - 1456                    
AC代码1(比着之前做过的一道题<H>的代码改了改就交了,未用到并查集,不过时间复杂度好像有点高,157MS):
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int maxn = 10005;int a[10005];struct node{    int sco, ded;};int cmp(node x, node y){    if(x.sco == y.sco)        return x.ded < y.ded;    return x.sco > y.sco;}int main(){    int t, n;    while(~scanf("%d",&n))    {        long long sum = 0;        node f[maxn];        for(int i = 0; i < n; ++i)        {            scanf("%d",&f[i].sco);            scanf("%d",&f[i].ded);            sum += f[i].sco;        }        sort(f, f+n, cmp);        long long ans = 0;        memset(a, 0, sizeof(a));        for(int i = 0; i < n; ++i)        {            int tem;            for(tem = f[i].ded; tem > 0; --tem)            {                if(a[tem] == 0)                {                    a[tem] = 1;                    break;                }            }            if(tem == 0)                ans += f[i].sco;        }        cout << sum - ans << endl;    }    return 0;}
AC代码(并查集,63MS):
/*************************************************************************主要思想:1.按照价值问题进行排列(贪心2.回溯找值//每次回溯,找前面如果有一个点f[i]==i,那么此点可以使用,就可以停止回溯//此外此点自己--,表示该时间也被使用//后面如果回溯到该点的时候不可以停止下来,仍然需要向前回溯//如果一直回溯到0,那么就是没有位置可以进行//那么这次的价值也不会算到总和里面*************************************************************************/#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int MAX = 1e4 + 5;int f[MAX];struct node{    int value;    int time;};bool cmp(node a, node b){    if(a.value == b.value) return a.time > b.time;    return a.value > b.value;}void init(){    for(int i = 0; i < MAX; ++i)        f[i] = i;}int getf(int v){    if(f[v] != v)        f[v] = getf(f[v]);    return f[v];}int main(){    int n;    while(~scanf("%d",&n))    {        init();        node que[MAX];        for(int i = 0; i < n; ++i)        {            scanf("%d%d",&que[i].value,&que[i].time);        }        sort(que, que + n, cmp);        int ans = 0;        for(int i = 0; i < n; ++i)        {            int tem = que[i].time;            int xx = getf(tem);            if(xx > 0)            {                f[xx]--;                ans += que[i].value;            }        }        cout << ans << endl;    }    return 0;}


H - Parity game

POJ - 1733                    

※AC代码:

#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int N = 5005;int a[N*2], n, q, cnt;int f[N*2], r[N*2];struct node{    int u, v;    char str[10];} que[N];void init(){    for(int i = 0; i < cnt; ++i)    {        f[i] = i;        r[i] = 0;    }}int getf(int v){    if(v != f[v])    {        int tem = f[v];        f[v] = getf(f[v]);        r[v] = r[v] ^ r[tem];    }    return f[v];}int bin(int v){    int low = 0;    int high = cnt - 1;    int mid;    while(low <= high)    {        mid = (low + high) / 2;        if(a[mid] == v) return mid;        if(a[mid] < v) low = mid + 1;        else high = mid - 1;    }    return -1;}int main(){    while(~scanf("%d",&n))    {        scanf("%d",&q);        cnt = 0;        for(int i = 0; i < q; ++i)        {            //注意输入的是数字 数字 字符串            scanf("%d%d%s",&que[i].u,&que[i].v,&que[i].str);            que[i].u--;            a[cnt++] = que[i].v;            a[cnt++] = que[i].u;        }        sort(a, a+cnt);        cnt = unique(a, a+cnt) - a;        init();        int ans = 0;        for(int i = 0; i < q; ++i)        {            //这一块按照习惯可以改为一个merg函数            int u = bin(que[i].u);            int v = bin(que[i].v);            int t1 = getf(u);            int t2 = getf(v);            if(t1 == t2)            {                if(r[u] == r[v] && que[i].str[0] == 'o') break;                if(r[u] != r[v] && que[i].str[0] == 'e') break;                ans++;            }            else            {                if(que[i].str[0] == 'o')                {                    f[t1] = t2;                    r[t1] = r[u] ^ r[v] ^ 1;                }                else                {                    f[t1] = t2;                    r[t1] = r[u] ^ r[v];                }                ans++;            }        }        cout << ans << endl;    }    return 0;}


I - Navigation Nightmare

POJ - 1984                    

※AC代码:

#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int MAX = 4e4 + 5;const int MMM = 1e4 + 5;int n, m, k;int f[MAX], ans[MMM];int x[MAX], y[MAX];     //记录坐标int dx[MAX], dy[MAX];   //方向(相对位置)int rx[MAX], ry[MAX];   //最后位置struct node             //记录要查询的内容{    int x, y, idx;      //x,y是坐标,idx是询问的时间    int n;              //记录出现的顺序,方便最后输出}F[MMM];//按照询问时间的先后顺序从小到大排序bool cmp(node u, node v){    return u.idx < v.idx;}void init(){    for(int i = 0; i <= n; ++i)    {        f[i] = i;        rx[i] = ry[i] = 0;    }}int getf(int v){    if(f[v] == v) return v;    int tem = f[v];    f[v] = getf(f[v]);    rx[v] += rx[tem];    ry[v] += ry[tem];    return f[v];}void merg(int u, int v, int tt){    int t1 = getf(u);    int t2 = getf(v);    f[t2] = t1;    rx[t2] = rx[u] - rx[v] - dx[tt];    ry[t2] = ry[u] - ry[v] - dy[tt];    return ;}int main(){    int w, T;    char ch;    scanf("%d%d",&n,&m);    init();    for(int i = 1; i <= m; ++i)    {        scanf("%d%d%d %c",&x[i], &y[i], &w, &ch);        switch(ch)        {            case 'E': dx[i] = w; dy[i] = 0; break;            case 'W': dx[i] = -w; dy[i] = 0; break;            case 'N': dx[i] = 0; dy[i] = w; break;            case 'S': dx[i] = 0; dy[i] = -w; break;        }    }    scanf("%d",&T);    for(int i = 1; i <= T; ++i)    {        scanf("%d%d%d",&F[i].x,&F[i].y,&F[i].idx);        F[i].n = i;    }    sort(F+1, F+T+1, cmp);    //按照询问的先后进行排序    for(int i = 1; i <= T; ++i)    {        //不断加入点的集合,截止到第F[i].idx次        for(int j = F[i-1].idx; j <= F[i].idx; ++j)        {            merg(x[j], y[j], j);        }        if(getf(F[i].x) != getf(F[i].y)) //不连通            ans[F[i].n] = -1;        else                   //求出他们的曼哈顿距离            ans[F[i].n] = abs(rx[F[i].x] - rx[F[i].y]) + abs(ry[F[i].x] - ry[F[i].y]);    }    for(int i = 1; i <= T; ++i)        cout << ans[i] << endl;    return 0;}


J - A Bug's Life

POJ - 2492                    

AC代码:

#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int MAX = 4005;int f[MAX];int n, m;void init(int n){    for(int i = 1; i <= n; ++i)        f[i] = i;}int getf(int v){    if(f[v] != v)        f[v] = getf(f[v]);    return f[v];}void merg(int u, int v){    int t1 = getf(u);    int t2 = getf(v);    if(t1 != t2)        f[t1] = t2;}bool same(int u, int v){    return getf(u) == getf(v);}int main(){    int T;    bool flag;    int x, y;    scanf("%d",&T);    for(int i = 1; i <= T; ++i)    {        flag = true;        printf("Scenario #%d:\n", i);        scanf("%d%d",&n,&m);        init(2*n);        while(m--)        {            scanf("%d%d",&x, &y);            if(same(x, y))            {                flag = false;            }            else            {                merg(x, y+n);                merg(y, x+n);            }        }        if(flag)            printf("No suspicious bugs found!\n");        else            printf("Suspicious bugs found!\n");        //if(i != 1) 本来是想这个防PE的,结果用了这个就PE了        cout << endl;    }    return 0;}


K - Rochambeau

POJ - 2912                    

※AC代码:
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int N = 505;const int M = 2005;int n, m;bool flag;int f[N], r[N], error[N];struct Node{    int u, v, k;} a[M];void init(){    for(int i = 0; i < n; ++i)    {        f[i] = i;        r[i] = 0;    }}int getf(int v){    if(v != f[v])    {        int tem = f[v];        f[v] = getf(f[v]);        r[v] = (r[v] + r[tem]) % 3;    }    return f[v];}//有错误&&还没找出来(懒得找了/*void merg(int i, int j, int x, int y, int z){    if(i == x || i == y) return ;    int t1 = getf(x);    int t2 = getf(y);    if(t1 == t2)    {        if(z==0 && r[x] != r[y])        {            error[i] = j + 1;            flag = true;            return ;        }        if(z==1 && (r[x]+1)%3 != r[y])        {            error[i] = j + 1;            flag = true;            return ;        }        if(z==2 && (r[x]+2)%3 != r[y])        {            error[i] = j + 1;            flag = true;            return ;        }    }    else    {        f[t2] = t1;        r[t2] = (r[x] - r[y] + 3 + z + r[t1]) % 3;    }}*/int main(){    char ch;    while(~scanf("%d%d",&n,&m))    {        flag = false;        for(int i=0; i<m; i++)        {            scanf("%d",&a[i].u);            char ch;            while((ch=getchar())==' ');            scanf("%d",&a[i].v);            a[i].k=(ch=='=')?0:(ch=='<'?1:2);        }        memset(error, -1, sizeof(error));        for(int i = 0; i < n; ++i)        {            init();            for(int j = 0; j < m; ++j)            {                /*merg(i, j, a[j].u, a[j].v, a[j].k);                if(flag) break;*/                if(i==a[j].u||i==a[j].v) continue;                int ra=getf(a[j].u),rb=getf(a[j].v);                if(ra==rb)                {                    if(a[j].k==0&&r[a[j].u]!=r[a[j].v])                    {                        error[i]=j+1;                        break;                    }                    if(a[j].k==1&&(r[a[j].u]+1)%3!=r[a[j].v])                    {                        error[i]=j+1;                        break;                    }                    if(a[j].k==2&&(r[a[j].u]+2)%3!=r[a[j].v])                    {                        error[i]=j+1;                        break;                    }                }                else                {                    f[rb]=ra;                    r[rb]=(r[a[j].u]-r[a[j].v]+3+a[j].k+r[ra])%3;                }            }        }        int cou, a1, a2;        cou = a1 = a2 = 0;        for(int i = 0; i < n; ++i)        {            if(error[i] == -1)            {                cou++;                a1 = i;            }            a2 = max(a2, error[i]);        }        if(cou == 0) puts("Impossible");        else if(cou > 1) puts("Can not determine");        else printf("Player %d can be determined to be the judge after %d lines\n",a1,a2);    }    return 0;}


L - Connections in Galaxy War

ZOJ - 3261                    

※AC代码:
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <cmath>#include <map>#include <vector>using namespace std;const int M = 5e4 + 5;const int N = 1e4 + 5;struct node{    int a, b, k;} que[M];map<pair<int, int>, int> edge;int f[N], num[N], val[N];int n, m, q;void init(){    for(int i = 0; i < n; ++i)    {        f[i] = i;        num[i] = val[i];    }}int getf(int v){    if(v != f[v])    {        int tem = f[v];        f[v] = getf(f[v]);        num[v] = max(num[v], num[tem]);    }    return f[v];}void merg(int u, int v){    int t1 = getf(u);    int t2 = getf(v);    if(t1 == t2) return ;    if(num[t1] > num[t2] || (num[t1] == num[t2] && t1 < t2))        f[t2] = t1;    else  f[t1] = t2;}int main(){    bool flag = false;    while(~scanf("%d",&n))    {        if(flag) cout << endl;        else flag = true;        for(int i = 0; i < n; ++i)            scanf("%d",&val[i]);        edge.clear();        scanf("%d",&m);        init();        for(int i = 0; i < m; ++i) //创建道路        {            int u, v;            scanf("%d%d",&u,&v);            if(u > v) swap(u, v);            edge[make_pair(u, v)] = 1;        }        scanf("%d",&q);        for(int i = 0; i < q; ++i)        {            char str[10];            scanf("%s",str);            if(str[0] == 'q') //查询            {                scanf("%d",&que[i].a);                que[i].k = 0;            }            else             //摧毁道路            {                scanf("%d%d",&que[i].a,&que[i].b);                if(que[i].a > que[i].b) swap(que[i].a, que[i].b);                edge[make_pair(que[i].a, que[i].b)] = 0;                que[i].k = 1;            }        }        map<pair<int, int>, int> :: iterator it;        for(it = edge.begin(); it != edge.end(); ++it)        {            if(it -> second)            {                pair<int, int> tem = it -> first;                merg(tem.first, tem.second);            }        }        vector<int> ans;        ans.clear();        for(int i = q-1; i >= 0; --i)        {            if(que[i].k == 0)            {                if(num[getf(que[i].a)] <= val[que[i].a])                    ans.push_back(-1);                else                    ans.push_back(getf(que[i].a));            }            else  merg(que[i].a, que[i].b);        }        for(int i = ans.size()-1; i >= 0; --i)            cout << ans[i] << "\n";    }    return 0;}


M - 小希的迷宫

HDU - 1272                    

AC代码:

#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int MAX = 1e5 + 5;int f[MAX];bool vis[MAX];int n, m;void init(){    for(int i = 0; i < MAX; ++i)    {        f[i] = i;        vis[i] = false;    }}int getf(int v){    if(f[v] != v)        f[v] = getf(f[v]);    return f[v];}bool merg(int u, int v){    int t1 = getf(u);    int t2 = getf(v);    if(t1 != t2)    {        f[t1] = t2;        return true;    }    return false;  //两点的根节点一样——成环}int main(){    while(scanf("%d%d",&n,&m) && (n != -1 || m != -1))    {        if(!n && !m)  //如果第一组就是0 0        {            cout << "Yes" << endl;            continue;        }        init();        //开始建树        vis[n] = vis[m] = true;        bool flag = merg(n, m);        while(scanf("%d%d",&n,&m) && (n || m))        {            vis[n] = vis[m] = true;            if(!merg(n, m))  flag = false;        }        int cou = 0;        if(!flag)        {            cout << "No" << endl;            continue;        }        else        {            for(int i = 0; i < MAX; ++i)                if(vis[i] && f[i] == i) cou++;        }        if(cou > 1)        {            cout << "No" << endl;            continue;        }        cout << "Yes" << endl;    }    return 0;}


N - Is It A Tree?

POJ - 1308                    

#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int MAX = 1e5 + 5;int f[MAX];bool vis[MAX];int n, m;void init(){    for(int i = 0; i < MAX; ++i)    {        f[i] = i;        vis[i] = false;    }}int getf(int v){    if(f[v] != v)        f[v] = getf(f[v]);    return f[v];}bool merg(int u, int v){    int t1 = getf(u);    int t2 = getf(v);    if(t1 != t2)    {        f[t1] = t2;        return true;    }    return false;  //两点的根节点一样——成环}int main(){    int cas = 0;    while(scanf("%d%d",&n,&m) && (n != -1 || m != -1))    {        if(!n && !m)  //如果第一组就是0 0        {            printf("Case %d is a tree.\n", ++cas);            continue;        }        init();        //开始建树        vis[n] = vis[m] = true;        bool flag = merg(n, m);        while(scanf("%d%d",&n,&m) && (n || m))        {            vis[n] = vis[m] = true;            if(!merg(n, m))  flag = false;        }        int cou = 0;        if(!flag)        {            printf("Case %d is not a tree.\n", ++cas);            continue;        }        else        {            for(int i = 0; i < MAX; ++i)                if(vis[i] && f[i] == i) cou++;        }        if(cou > 1)        {            printf("Case %d is not a tree.\n", ++cas);            continue;        }        printf("Case %d is a tree.\n", ++cas);    }    return 0;}


0 0