CodeForces - 19E Fairy(图论 + DP)
2016-11-07 16:02
225 查看
Description
Once upon a time there lived a good fairy A. One day a fine young man B came to her and asked to predict his future. The fairy looked into her magic ball and said that soon the fine young man will meet the most beautiful princess ever and will marry her.
Then she drew on a sheet of paper n points and joined some of them with segments, each of the segments starts in some point and ends in some other point. Having drawn that picture, she asked
the young man to erase one of the segments from the sheet. Then she tries to colour each point red or blue so, that there is no segment having points of the same colour as its ends. If she manages to do so, the prediction will come true. B wants to meet the
most beautiful princess, that's why he asks you to help him. Find all the segments that will help him to meet the princess.
Input
The first input line contains two integer numbers: n — amount of the drawn points and m — amount of the drawn segments (1 ≤ n ≤ 104, 0 ≤ m ≤ 104).
The following m lines contain the descriptions of the segments. Each description contains two different space-separated integer numbers v, u (1 ≤ v ≤ n, 1 ≤ u ≤ n)
— indexes of the points, joined by this segment. No segment is met in the description twice.
Output
In the first line output number k — amount of the segments in the answer. In the second line output k space-separated numbers
— indexes of these segments in ascending order. Each index should be output only once. Segments are numbered from 1 in the input order.
Sample Input
Input
Output
Input
Output
Source
Codeforces Beta Round #19
题意:给一个无向图,现在让你删一条边,使得删后的图为二分图,要求输出所有删边方案。
分析:一个无向图为二分图的充要条件是图中无奇环。我们可以对原图做一遍dfs,这样可以将图中的所有环分解为一个个“基环”,基环只有一个连向祖先的边,且图中所有的环都可以由几个基环的边异或得到,因为要求删一条边后图中不存在基环,所以这条边至少要存在于所有的奇数基环中,然后考虑它是不是也存在于所有的奇环中,这时我们可以注意到如果这条边同时被一个偶数基环覆盖,那么无论删不删这条边都会存在一个复合的奇环,这样我们就得到了一个必要条件,然后我们证明这个条件也是充分条件:如果我们删掉这条边,那么便破坏了图中所有的奇基环,此时图中仅存在偶基环,又因为所有的复合奇环至少有一个奇基环参与,且我们删的这条边同时也存在于复合后的大环中(因为没有偶基环覆盖它),所以此时图中也一定
无复合奇环。
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<ctime>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
#define INF 0x3f3f3f3f
#define eps 1e-9
#define N 10005
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
vector <pii> G
;
int n,m,u,v,tot_ans,tot_odd,edge_first,jud
,vis
,f_odd
,f_even
,dep
;
pii edge
;
void dfs(int u,int fa,int edg)
{
if(fa > 0) dep[u] = dep[fa] + 1;
vis[u] = true;
for(int i = 0;i < G[u].size();i++)
{
int v = G[u][i].first,e = G[u][i].second;
if(v != fa)
if(vis[v])
{
if(dep[v] > dep[u]) continue; //防止反向边重复
if((dep[u] - dep[v]) & 1)
{
f_even[u]++;
f_even[v]--;
}
else
{
tot_odd++;
edge_first = e;
f_odd[u]++;
f_odd[v]--;
}
}
else
{
dfs(v,u,e);
f_even[u] += f_even[v];
f_odd[u] += f_odd[v];
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1;i <= m;i++)
{
scanf("%d%d",&u,&v);
G[u].push_back(make_pair(v,i));
G[v].push_back(make_pair(u,i));
edge[i] = make_pair(u,v);
}
for(int i = 1;i <= n;i++)
if(!vis[i]) dfs(i,-1,-1);
if(!tot_odd)
{
printf("%d\n",m);
for(int i = 1;i <= m;i++) printf("%d ",i);
return 0;
}
for(int i = 1;i <= m;i++)
{
int u = edge[i].first,v = edge[i].second;
if(dep[u] > dep[v]) swap(u,v);
if(i == edge_first && tot_odd == 1)
{
tot_ans++;
jud[i] = true;
}
if(dep[v] - dep[u] != 1) continue;
if(!f_even[v] && f_odd[v] == tot_odd)
{
tot_ans++;
jud[i] = true;
}
}
printf("%d\n",tot_ans);
for(int i = 1;i <= m;i++)
if(jud[i]) printf("%d ",i);
}
Once upon a time there lived a good fairy A. One day a fine young man B came to her and asked to predict his future. The fairy looked into her magic ball and said that soon the fine young man will meet the most beautiful princess ever and will marry her.
Then she drew on a sheet of paper n points and joined some of them with segments, each of the segments starts in some point and ends in some other point. Having drawn that picture, she asked
the young man to erase one of the segments from the sheet. Then she tries to colour each point red or blue so, that there is no segment having points of the same colour as its ends. If she manages to do so, the prediction will come true. B wants to meet the
most beautiful princess, that's why he asks you to help him. Find all the segments that will help him to meet the princess.
Input
The first input line contains two integer numbers: n — amount of the drawn points and m — amount of the drawn segments (1 ≤ n ≤ 104, 0 ≤ m ≤ 104).
The following m lines contain the descriptions of the segments. Each description contains two different space-separated integer numbers v, u (1 ≤ v ≤ n, 1 ≤ u ≤ n)
— indexes of the points, joined by this segment. No segment is met in the description twice.
Output
In the first line output number k — amount of the segments in the answer. In the second line output k space-separated numbers
— indexes of these segments in ascending order. Each index should be output only once. Segments are numbered from 1 in the input order.
Sample Input
Input
4 4 1 2 1 3 2 4 3 4
Output
4 1 2 3 4
Input
4 5 1 2 2 3 3 4 4 1 1 3
Output
1 5
Source
Codeforces Beta Round #19
题意:给一个无向图,现在让你删一条边,使得删后的图为二分图,要求输出所有删边方案。
分析:一个无向图为二分图的充要条件是图中无奇环。我们可以对原图做一遍dfs,这样可以将图中的所有环分解为一个个“基环”,基环只有一个连向祖先的边,且图中所有的环都可以由几个基环的边异或得到,因为要求删一条边后图中不存在基环,所以这条边至少要存在于所有的奇数基环中,然后考虑它是不是也存在于所有的奇环中,这时我们可以注意到如果这条边同时被一个偶数基环覆盖,那么无论删不删这条边都会存在一个复合的奇环,这样我们就得到了一个必要条件,然后我们证明这个条件也是充分条件:如果我们删掉这条边,那么便破坏了图中所有的奇基环,此时图中仅存在偶基环,又因为所有的复合奇环至少有一个奇基环参与,且我们删的这条边同时也存在于复合后的大环中(因为没有偶基环覆盖它),所以此时图中也一定
无复合奇环。
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<ctime>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
#define INF 0x3f3f3f3f
#define eps 1e-9
#define N 10005
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
vector <pii> G
;
int n,m,u,v,tot_ans,tot_odd,edge_first,jud
,vis
,f_odd
,f_even
,dep
;
pii edge
;
void dfs(int u,int fa,int edg)
{
if(fa > 0) dep[u] = dep[fa] + 1;
vis[u] = true;
for(int i = 0;i < G[u].size();i++)
{
int v = G[u][i].first,e = G[u][i].second;
if(v != fa)
if(vis[v])
{
if(dep[v] > dep[u]) continue; //防止反向边重复
if((dep[u] - dep[v]) & 1)
{
f_even[u]++;
f_even[v]--;
}
else
{
tot_odd++;
edge_first = e;
f_odd[u]++;
f_odd[v]--;
}
}
else
{
dfs(v,u,e);
f_even[u] += f_even[v];
f_odd[u] += f_odd[v];
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1;i <= m;i++)
{
scanf("%d%d",&u,&v);
G[u].push_back(make_pair(v,i));
G[v].push_back(make_pair(u,i));
edge[i] = make_pair(u,v);
}
for(int i = 1;i <= n;i++)
if(!vis[i]) dfs(i,-1,-1);
if(!tot_odd)
{
printf("%d\n",m);
for(int i = 1;i <= m;i++) printf("%d ",i);
return 0;
}
for(int i = 1;i <= m;i++)
{
int u = edge[i].first,v = edge[i].second;
if(dep[u] > dep[v]) swap(u,v);
if(i == edge_first && tot_odd == 1)
{
tot_ans++;
jud[i] = true;
}
if(dep[v] - dep[u] != 1) continue;
if(!f_even[v] && f_odd[v] == tot_odd)
{
tot_ans++;
jud[i] = true;
}
}
printf("%d\n",tot_ans);
for(int i = 1;i <= m;i++)
if(jud[i]) printf("%d ",i);
}
相关文章推荐
- Codeforces 913F Strongly Connected Tournament 期望dp+图论
- Codeforces 19E Fairy
- bzoj 4424: Cf19E Fairy && codeforces 19E. Fairy【树形dp】
- Codeforces 467D. Fedor and Essay (Graphs,dfs,dp,hashing,strings,图论综合型好题)
- 【CodeForces】919B- Substring 图论,dp
- codeforces 580D Kefa and Dishes【状态压缩+dp】
- 【codeforces】55D. Beautiful numbers 数位DP
- Codeforces 294E Shaass the Great 树形dp(水
- CodeForces 219D Choosing Capital for Treeland (树形dp)
- Codeforces 148 E Porcelain【dp】
- Codeforces-936B:Sleepy Game(DP)
- codeforces 545C C. Woodcutters(dp+二分)
- CodeForces 106C 【DP】
- CodeForces - 148D Bag of mice(概率dp)
- codeforces 258div2 A Game With Sticks(DP)
- Codeforces 868F - Yet Another Minimization Problem (分治DP,莫队)
- CodeForces - 711C Coloring Trees(DP)(思维)
- Codeforces 414B 统计dp
- Codeforces 86C Genetic engineering(AC自动机+DP)
- Codeforces-903F:Clear The Matrix(轮廓线DP)