搜索2

P8604 [蓝桥杯 2013 国 C] 危险系数

暴力删除点,然后判断能否走过去

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N =2e3+100;
int ver[N] , Next[N];
int head[N << 1] , vis[N];
int n , m , tot;
int u , v;
 void add(int u,int v)
{
   ver[++tot] = v;
   Next[tot] = head[u];
   head[u] = tot;
}
int flag ; 
void dfs(int x ,int f){
	if(x == v){
		flag = 1;
		return ;
	}
	for(int i = head[x] ; i ; i = Next[i]){
		int y = ver[i];
		if(vis[y] || y == f)continue;
		if(y == v){
			flag = 1;
			return ;
		}	
		 dfs(y , x); 
	}
	return ;
}
int main()
{
	scanf("%d%d", &n , &m);
	int x , y;
	for(int i = 1;i <= m  ;i ++)
	{
		scanf("%d%d", &x , &y);
		add(x , y);
		add(y , x);
	}
	scanf("%d%d",&u , &v);
	int ans = 0;
	for(int i = 1;i <= n ;i ++)
	{
		if(i == u || i == v) continue;
		memset(vis , 0 , sizeof vis);
		vis[i] = 1;
		flag = 0;
		dfs(ver[Next[u]] , u);
		if(!flag) ans++;
	}
	printf("%d\n",ans);
	return 0;
}

P3916 图的遍历

倒着做,较大的点可以到达的点,这些y到达的最大点也一定是 x

#include<bits/stdc++.h>
using namespace std;
int n , m;
int a[1000002];
vector<int>G[1000020];
void dfs(int x, int d){
	if(a[x]) return ;
	a[x] = d;
	for(int i = 0 ; i < G[x].size( ) ;i++){
		dfs(G[x][i] , d);
	}
}
int main () {
	scanf("%d%d",&n ,&m);
	for(int i = 1 ; i <= m; i++){
		int x , y;
       scanf("%d%d" , &x , &y);
       G[y].push_back(x);
	}
	for(int i = n; i >= 1 ; i--){
	     dfs(i , i);
	}
	for(int i = 1; i <= n ;i++){
		cout << a[i] << " " ;
	}
}
//基本思路 , 有两种染色方案
对于一个连通图,要不就只有两种选法(因为可以全部选染成一种色的,也可以全部选染成另一种色的),要不就是impossible
所以依据这个思路 来说 记一下自己的和自己不同的,
找到他们的根节点 , 然后判断一下size数组的大小,加上一个小的, 方是正解
#include<bits/stdc++.h>
using namespace std;
//v数组用来标记 , f常规数组 , dif用来判断和自己不同的颜色 , sum用来记录答案数量

bool v[100020];
int f[100001] ;
int n , m;
int dif[100020];
int sum[100020];
int F(int x){
    if(x == f[x]){
        return x;
    }
    return f[x] = F(f[x]);
}
void wjz_(int x ,int y){
    int xx = F(x)
    if(xx != y){
        f[xx] = y;
       sum[y] += sum[xx];//累加
    }
}

int main () {
    scanf("%d%d" ,&n ,&m);
    for(int i = 1; i <= n ;i++){
        f[i] = i;
        sum[i] = 1;
    }
    for(int i = 0; i < m; i++){
        int a , b;
        scanf("%d%d" ,&a ,&b);
       int xx = F(a);
       int yy = F(b);
       if(xx != yy){
        if(dif[a]) wjz_(dif[a] , yy);//如果dif存在 ,因为x和y不同色, 所以他与yy一起
        if(dif[b]) wjz_(dif[b] , xx);
        dif[a] = yy;
        dif[b] = xx;//等于自己当前的根
       }else{
        cout << "Impossible" <<endl;
        return 0;
       }
    }
    int ans = 0;
    for(int i = 1; i <= n ; i++){
        int w = F(i);//找自己的根节点以及与自己不同的根节点
        if(!v[w]){
            int wj = F(dif[i]);
            v[w] = 1;
            v[wj] = 1;
            ans += min(sum[w] , sum[wj]);
        }
    }
    cout << ans << endl;

}
posted @ 2022-11-23 16:49  wmjlzw1314  阅读(275)  评论(0)    收藏  举报