Linking
题目:
给出
n
n
n 个点
m
m
m 条边 的无向图,给出
k
k
k 个点,这
k
k
k 个点上每个点都有一个人,每个人每回合能走到一个相邻的节点(不能停留不走),问:有没有可能在某一个回合,让这些人都集中在一个点?
1
≤
n
,
k
≤
2
e
5
,
0
≤
m
≤
m
i
n
(
5
e
5
,
n
∗
(
n
−
1
)
/
2
)
1\le n,k\le 2e5,0\le m\le min(5e5,n*(n-1)/2)
1≤n,k≤2e5,0≤m≤min(5e5,n∗(n−1)/2)
思路:
如果所有有人的点都可以被染成黑色或白色,那么这些人可以集中到同一点。
用 color[i][0]
表示 i 点是否可以被染成黑色,color[i][1]
表示 i 点是否可以被染成白色。
如果值为1,说明可以染成。值为0说明不可以染成。
注意数据范围,边数m很多,所以用数组模拟邻接表存不下。可以开vector来代替数组。
模板:
while(m--) //vector h[i]中存储的是点i相连的所有点。
{
cin>>x>>y;
h[x].push_back(y);
h[y].push_back(x);
}
for(auto tx:h[x])
{
//tx为和点x相连的点。
}
Code:
const int N = 500010, mod = 1e9+7;
int T, n, m, k;
int a[N], b[N];
vector<int> h[N];
int color[N][2];
void dfs(int x)
{
for(auto tx:h[x])
{
if(color[x][0])
{
if(!color[tx][1]) color[tx][1]=1, dfs(tx);
}
if(color[x][1])
{
if(!color[tx][0]) color[tx][0]=1, dfs(tx);
}
}
}
void bfs(int st)
{
queue<int> que;
que.push(st);
color[st][0]=1;
while(que.size())
{
int x=que.front();
que.pop();
if(color[x][0])
{
for(int i=0;i<h[x].size();i++)
{
int tx=h[x][i];
if(!color[tx][1]) color[tx][1]=1, que.push(tx);
}
}
if(color[x][1]){
for(int i=0;i<h[x].size();i++)
{
int tx=h[x][i];
if(!color[tx][0]) color[tx][0]=1, que.push(tx);
}
}
}
}
signed main(){
Ios;
cin>>n>>m>>k;
while(m--)
{
int x,y;cin>>x>>y;
h[x].push_back(y);
h[y].push_back(x);
}
for(int i=1;i<=k;i++) cin>>b[i];
bfs(1);
// color[1][0]=1;
// dfs(1);
int flag1=1, flag2=1;
for(int i=1;i<=k;i++)
{
// cout<<color[b[i]][1]<<" ";
if(!color[b[i]][0]) flag1=0;
if(!color[b[i]][1]) flag2=0;
}
if(flag1 || flag2) cout<<"YES";
else cout<<"NO";
return 0;
}
要掌握用vector存图的方法。