码迷,mamicode.com
首页 > 其他好文 > 详细

fzu2181(点的双连通分量+求奇环)

时间:2014-11-19 00:18:20      阅读:181      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   io   ar   color   os   sp   for   

求出每个点双连通分量,如果在一个点双连通分量中有奇环,则这个分量每个点都在一个奇环中。  关键是要知道怎么求点双连通分量以及点双连通的性质。

 

fzu2181 http://acm.fzu.edu.cn/problem.php?pid=2181

 

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 1100

int n,m,k;
int g[N][N];
int vis[N];
int height[N];
int stk[N];
int deep,top;
int mark[N];
int save[N]; //用来记录特殊状态
int ans;

int dfs(int s,int num)
{
    vis[s]=deep++;
    stk[top++]=s;
    height[s]=num;
    int mi=vis[s];
    for(int i=1;i<=n;i++)
    {
        if(g[s][i]==0) continue;
        if(vis[i]==-1) //这个点未被访问
        {
            dfs(i,num+1);
            if( vis[i]>=vis[s] )//表示这个圈与世无争,必须单独处理掉
            {
                //开始处理!
                int cnt=0;
                int tcnt=0;
                int flag=0;
                while(stk[top-1]!=s)
                {
                    cnt++;
                    if(mark[stk[top-1]]==1) flag=1;//表示这一堆有奇环
                    if(save[stk[top-1]]==1) tcnt++;
                    top--;
                }

                if(flag==1)//这一堆不存在奇环
                {
                    save[s]=1;
                    ans += cnt+1-tcnt;
                }

            }
            else
            {
                mi = min(mi,vis[i]);
            }
        }
        else
        {
            mi=min(mi,vis[i]);//找当前能到达最上方的点
            if( (height[s]-height[i])%2==0 )//表示当前点在一个奇环中
                mark[s]=1;
        }
    }
    vis[s]=mi;
    return vis[s];
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&m,&k);
        memset(g,0,sizeof(g));
        for(int i=0;i<m;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            g[x][y]=g[y][x]=1;
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                if(i==j) g[i][j]=0;
                else if(g[i][j]==1) g[i][j]=0;
                else g[i][j]=1;
            }
        //构建逆图
        memset(vis,-1,sizeof(vis));
        memset(save,0,sizeof(save));
        memset(mark,0,sizeof(mark));
        deep=0;
        top=0;
        ans=0;//表示有多少不能参与游戏
        for(int i=1;i<=n;i++)
        {
            if(vis[i]==-1)
            {
                dfs(i,0);
            }
        }
        if(ans<k) printf("What a Pity.\n");
        else printf("Let‘s Fire!\n");
    }
    return 0;
}

 

fzu2181(点的双连通分量+求奇环)

标签:style   blog   http   io   ar   color   os   sp   for   

原文地址:http://www.cnblogs.com/chenhuan001/p/4106849.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!