閱讀885 返回首頁    go 外匯


poj 2942 Knights of the Round Table 點重聯通分量

  書上把這放在邊聯通的第一道題,於是一開始就按邊寫了,一直寫不對,重新想了一遍,才發現是點聯通……


/*
author:jxy
lang:C/C++
university:China,Xidian University
**If you need to reprint,please indicate the source**
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <stack>
#define pb push_back
using namespace std;
int n,m;
int Map[1005][1005];
vector<int> org[1005];
vector<int> belong[1005];
int vis[1005];
int dph[1005],low[1005];
int d;
int num=0;
bool ok[1005];
stack<int> S;
void dfs(int v,int f)
{
    vis[v]=1;
    dph[v]=low[v]=d++;
    S.push(v);
    for(int i=0; i<org[v].size(); i++)
    {
        int u=org[v][i];
        if(u==f)continue;
        if(vis[u]==1)low[v]=min(low[v],dph[u]);
        else if(!vis[u])
        {
            dfs(u,v);
            low[v]=min(low[v],low[u]);
            if(low[u]>=dph[v])
            {
                num++;
                belong[v].pb(num);
                belong[u].pb(num);
                while(S.top()!=u)// 注意邊界,如果吧push放在for循環裏就是!=v不用pop,否則就是!=u最後還要pop
                {
                    belong[S.top()].pb(num);
                    S.pop();
                }
                S.pop();
            }
        }
    }
    vis[v]=2;
}
int Tarjan() //搜索重聯通分量
{
    num=0;
    while(!S.empty())S.pop();
    for(int i=1; i<=n; i++)
    {
        d=0;
        if(!vis[i])
            dfs(i,-1);
    }
}
int dye(int v,int c,int flag)//1,-1染色
{
    vis[v]=c;
    for(int i=0; i<org[v].size(); i++)
    {
        int &u=org[v][i];
        if(ok[u])
        {
            if(vis[u]==0&&dye(u,-c,flag))return 1;
            if(vis[u]==c)return 1;
        }
    }
    return 0;
}
int use[1005];
int Count()
{
    int ans=0;

    memset(use,0,sizeof(use));
    for(int k=1; k<=num; k++)
    {
        memset(ok,0,sizeof(ok));
        memset(vis,0,sizeof(vis));
        for(int i=1; i<=n; i++)
        {
            if(find(belong[i].begin(),belong[i].end(),k)!=belong[i].end())
                ok[i]=1;
        }
        for(int i=1; i<=n; i++)
        {
            if(ok[i])
            {
                if(dye(i,1,k))
                    for(int j=1; j<=n; j++)
                        use[j]+=ok[j];
                break;
            }
        }
    }
    for(int i=1; i<=n; i++)
        if(!use[i])ans++;
    return ans;
}
int main()
{
    while(~scanf("%d%d",&n,&m)&&n+m)
    {
        int a,b;
        int i,j;
        memset(vis,0,sizeof(vis));
        memset(Map,0,sizeof(Map));
        for(i=1; i<=n; i++)
        {
            org[i].clear();
            belong[i].clear();
            Map[i][i]=1;
        }
        for(i=0; i<m; i++)
        {
            scanf("%d%d",&a,&b);
            Map[a][b]=Map[b][a]=1;
        }
        for(i=1; i<=n; i++) //建立不憎恨的圖
        {
            for(j=i; j<=n; j++)
                if(!Map[i][j])
                {
                    org[i].pb(j);
                    org[j].pb(i);
                }
        }
        Tarjan();
        printf("%d\n",Count());
    }
}


最後更新:2017-04-03 15:21:44

  上一篇:go 如何防止顯示全部上機學生時重複
  下一篇:go ARM相關知識