lightoj-1009 - Back to Underworld(dfs+仿二分图染色)

1009 - Back to Underworld
PDF (English) Statistics Forum
Time Limit: 4 second(s) Memory Limit: 32 MB
The Vampires and Lykans are fighting each other to death. The war has become so fierce that, none knows who will win. The humans want to know who will survive finally. But humans are afraid of going to the battlefield.

So, they made a plan. They collected the information from the newspapers of Vampires and Lykans. They found the information about all the dual fights. Dual fight means a fight between a Lykan and a Vampire. They know the name of the dual fighters, but don‘t know which one of them is a Vampire or a Lykan.

So, the humans listed all the rivals. They want to find the maximum possible number of Vampires or Lykans.

Input
Input starts with an integer T (≤ 10), denoting the number of test cases.

Each case contains an integer n (1 ≤ n ≤ 105), denoting the number of dual fights. Each of the next n lines will contain two different integers u v (1 ≤ u, v ≤ 20000) denoting there was a fight between u and v. No rival will be reported more than once.

Output
For each case, print the case number and the maximum possible members of any race.

Sample Input
Output for Sample Input
2
2
1 2
2 3
3
1 2
2 3
4 2
Case 1: 2
Case 2: 3

题目大意:给出N组对战的军队编号,求属于同个国家军队数的最大数量

解题思路: 每个连通的二分图中,只要有一个点确定是哪个国家的,那么整个连通图的节点所属的国家也就确定了。然后把每个连通图的计算出来较多的军队数相加起来。就搞定了。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;

const int N = 20010;
vector<int> vv[N];
bool uu[N],vis[N];

int T,n,u,v,maxn,minn,sum,sum1;

void init(){
    for(int i=0;i<N;i++) vv[i].clear();
    memset(uu,false,sizeof(uu));
    memset(vis,false,sizeof(vis));
    maxn = 0;
    minn = N;
}

void dfs(int u,bool flag){// flag 用来实现类似染色的功能,因为每次的染色不需要多次用到,所以直接传参过去就行了。 

    sum++;if(flag==1) sum1++;
    vis[u] = true;
    for(int i=0;i<vv[u].size();i++){

        if(vis[vv[u][i]]) continue;

        dfs(vv[u][i],!flag);

    }

    return ;
}

int main(){

    scanf("%d",&T);
    for(int t=1;t<=T;t++){
        init();
        scanf("%d",&n);
        for(int i=0;i<n;i++){

            scanf("%d%d",&u,&v);
            uu[u] = uu[v] = true;
            vv[u].push_back(v);
            vv[v].push_back(u);
            maxn = max(maxn,max(u,v));
            minn = min(minn,min(u,v));
        }
        int ans = 0;
        for(int i=minn;i<=maxn;i++){

            if(uu[i]==false||vis[i]==true) continue; // 不存在或者访问过的点 直接continue;
            sum = sum1 = 0;
            dfs(i,0);
            ans += max(sum1,sum-sum1);

        }
        printf("Case %d: %d\n",t,ans);
    }

    return 0;
}

时间: 2024-11-04 15:16:07

lightoj-1009 - Back to Underworld(dfs+仿二分图染色)的相关文章

【hiho】hiho第三十周&#183;二分图染色判定

是时候认真学学二分图了... 光会模板没用的,打好基础最重要~ 题目: 字面意思,二分图染色判断,判断是否是二分图 思路: 要让该无向图成为一张二分图,必须得将点划为G1,G2两个集合 也就是,对于给定的任何一条边,其连接的两个节点不能同色 那么我们可以总结出一个方法: 对于当前结点: 1.若其未被染色,我们规定将其染成A色,记为1 2.遍历其所有相邻的染色点,有未染色的,染为B色,记为2,DFS之 注:一旦被染色,说明此点状态被唯一确定 那么我们可以得到判断条件: 1.染色过程是否发生冲突 附

洛谷P1330 封锁阳光大学(二分图染色)

P1330 封锁阳光大学 题目描述 曹是一只爱刷街的老曹,暑假期间,他每天都欢快地在阳光大学的校园里刷街.河蟹看到欢快的曹,感到不爽.河蟹决定封锁阳光大学,不让曹刷街. 阳光大学的校园是一张由N个点构成的无向图,N个点之间由M条道路连接.每只河蟹可以对一个点进行封锁,当某个点被封锁后,与这个点相连的道路就被封锁了,曹就无法在与这些道路上刷街了.非常悲剧的一点是,河蟹是一种不和谐的生物,当两只河蟹封锁了相邻的两个点时,他们会发生冲突. 询问:最少需要多少只河蟹,可以封锁所有道路并且不发生冲突. 输

CODEVS1022 覆盖 (二分图染色+匈牙利算法)

先对整幅图进行二分图染色,再跑一遍匈牙利算法. 1 /* CODEVS1022 */ 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 7 #define maxn 10008 8 9 struct edge{ 10 int u,v,next; 11 }eg[maxn*4]; 12 13 int dx[4]={0,0,1,-1}; 14 i

POJ2942 Knights of the Round Table[点双连通分量|二分图染色|补图]

Knights of the Round Table Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 12439   Accepted: 4126 Description Being a knight is a very attractive career: searching for the Holy Grail, saving damsels in distress, and drinking with the oth

[NOIP2010]关押罪犯(二分+二分图染色)

传送门 大意:我们把图分为两部分,使得两部分中的内部边的最大权值最小. 思路:哎,拿到题的时候想了二分图染色,发现不好做,但我没有想到二分,只好最后去骗了一个30分.正确的思路是:首先我们要 去二分最大的冲突边的是哪一条(按照权值二分),因为当二分的边权增大时,连的边也就越少,连通块的数目就越多,冲突就越少,所以边权是可以二分的,在二分过后用二分图判定,如果可以染成二分图即为可行的解. 代码: #include<cstdio> #include<algorithm> #includ

BZOJ1443 游戏game (二分图染色+匈牙利算法)

先对整幅图进行二分图染色,再跑一遍匈牙利算法.如果最大匹配数=点数*2,那么输出WIN. 对于任何一个非必须在最大匹配上的点,即为所求的点. 1 Program Test375num2; 2 type arr=record 3 u,v,next:longint; 4 end; 5 const dx:array[1..4] of longint=(0,0,-1,1); 6 dy:array[1..4] of longint=(1,-1,0,0); 7 maxn=100008; 8 maxm=max

CodeForces - 862B Mahmoud and Ehab and the bipartiteness(二分图染色)

题意:给定一个n个点的树,该树同时也是一个二分图,问最多能添加多少条边,使添加后的图也是一个二分图. 分析: 1.通过二分图染色,将树中所有节点分成两个集合,大小分别为cnt1和cnt2. 2.两个集合间总共可以连cnt1*cnt2条边,给定的是一个树,因此已经连了n-1条边,所以最多能连cnt1*cnt2-(n-1)条边. 3.注意输出. #include<cstdio> #include<cstring> #include<cstdlib> #include<

GYM 100345E New Mayors(二分图染色)

题意:有一个无向图和三种颜色,顶点数目n<=500,记从一个顶点u出发所能到的所有顶点的集合为S(u),S(u)中的点可以相互到达且只经过S(u)中的点(不包括u),规定一条边的两个端点不能染相同的颜色,问是否存在一种可行方案. 思路:如果直接暴力的话时间复杂度是3^n,显然无法承受. 考虑任意一个结点u,那么S(u)中的所有点组成的子图是联通的并且S(u)中的点只能染另外两种颜色,由于这个图是联通的,所以染色方案肯定是唯一的,也就是说我们对于每个节点进行一次二分图染色,如果有冲突那么不存在方案

bzoj4881 [ Lydsy2017年5月月赛 ] -- 二分图染色+线段树

以下是Claris的题解: 若线段 i 和 j 相交,那么在它们之间连一条边.若这个图不是二分图,那么无解,否则令cnt 为连通块个数,那么 ans = 2cnt. 在二分图染色的过程中,每个点只需要被访问一次.对于当前所在的点 x,它可以一步走到 [1, x) 里 p[i] > p[x] 的所有 i,以及 (x, n] 里 p[j] < p[x] 的所有 j. 用线段树维护所有没走过的点,记录每个区间 p 最小与最大的两个位置.每次贪心取出最大/小的,看看是否满足条件, 若满足则删除该点,然