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());
    }
}


目录
相关文章
|
8月前
|
存储 Python
海明距离(Hamming Distance)
海明距离(Hamming Distance)是用来衡量两个二进制数之间差异程度的指标,它表示两个二进制数之间最多有多少个比特的差异。海明距离可以用于衡量数据传输或存储中的错误率,以及检测噪声干扰。 海明距离的计算方法是:对于两个 n 位二进制数,将它们进行逐位比较,如果对应位上的数字不同,则计算距离时增加 1。然后将所有位上的距离加在一起,得到海明距离。
942 1
|
8月前
|
算法
poj 2479 Maximum sum(求最大子段和的延伸)
看完最大连续子段和 的 dp算法 这个很容易理解,我用dplift[i]保存第1到第i个之间的最大子段和,dpright[i]保存第i到第n个之间的最大子段和,最终结果就是dplift[i]+dpright[i+1]中最大的一个。
32 0
|
1月前
|
C++
【PTA】​L1-048 矩阵A乘以B​ (C++)
【PTA】​L1-048 矩阵A乘以B​ (C++)
45 0
【PTA】​L1-048 矩阵A乘以B​ (C++)
|
1月前
HJ17 坐标移动
HJ17 坐标移动
43 0
|
8月前
|
Java
poj 1205 :Water Treatment Plants (DP+高精度)
思路:DP+高精度。DP部分,易得最右边城市的状态只可能用3种:>V, V, <。故分三种状态讨论,设dp[i][0]为第i个城市的状态为:> V ,dp[i][1]为:V ,dp[i][2]为:<。由实际流动的可能性可以得到状态转移方程:
23 0
|
8月前
华为机试HJ91:走方格的方案数
华为机试HJ91:走方格的方案数
2021杭电多校第八场 HDU7063-Square Card(求两圆相交面积)
2021杭电多校第八场 HDU7063-Square Card(求两圆相交面积)
58 0
2021杭电多校第八场 HDU7063-Square Card(求两圆相交面积)
[UVA1364 | POJ | NC]Knights of the Round Table | Tarjan 求点双 | 二分图 | 综合图论
我们可以很轻松地发现,被提出的都是在点双连通分量之外的,比如该图中的1 和 5 ,那么怎么判断哪些点不在环中呢? 此时我们还可以逆向思考,不 在 环 中 的 = = 总 的 − 在 环 中 的,所以说现在问题就转换成了满足条件的环内的点的个数
106 0
[UVA1364 | POJ | NC]Knights of the Round Table | Tarjan 求点双 | 二分图 | 综合图论