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

题目链接:点击打开链接

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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值