搜索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;
}

浙公网安备 33010602011771号