之前GCJ2014practice遇到过,当时推我google的liuchenheng大神说这个是最基础的题,
如果不会,就别来面了。我还真不会,可见有多弱。然后EMC summer campus时遇到USTC的李晨讯,看到输入,我一看就知道这题,他说他也写了半天才A的。
看来这种基础题需要熟练了,不仅要写出来,而且要快!
https://code.google.com/codejam/contest/2933486/dashboard
这题是裸的直接判是否是二分图,加一个color数组用染色的方法来判,是否可二染色,这是一个技巧
unordered_map<string,int> StrIndex;
int color[maxn];//0 not visit, 1 color1, 2 color2
vector<int> Edge[maxn];
int n, m;
bool dfs(int cur, int c)
{
if(color[cur]) return 1;
color[cur]=c;
for(auto i : Edge[cur]){
if(color[cur]==color[i] || (!color[i] &&!dfs(i,3-c))) return 0;
}
return 1;
}
/*
void dfs1(int cur, int c, int cnt){
color[cur]=c;
if(cnt==n){
int cnt1=0;
for(int i=1;i<=n;i++){
if(color[i]==1) cnt1++;
}
ans=max(cnt1, n-cnt1);
return ;
}
for(auto i: Edge[cur]){
if(color[cur]==color[i]) continue;
dfs1(i, 3-c, cnt+1);
}
}
*/
string str1, str2;
int main()
{
#ifndef ONLINE_JUDGE
freopen ("A-small-practice-2.in" , "r" , stdin);
freopen ("A-small-practice-2.out" , "w" , stdout);
#endif
int t;
cin>>t;
for(int ti=1;ti<=t;ti++)
{
StrIndex.clear();
n=0;
memset(color,0,sizeof color);
for(int i=0;i<maxn;i++) Edge[i].clear();
cin>>m;
for(int i=0;i<m;i++)
{
cin>>str1>>str2;
if(StrIndex.find(str1)==StrIndex.end()) StrIndex[str1]=n++;
if(StrIndex.find(str2)==StrIndex.end()) StrIndex[str2]=n++;
Edge[StrIndex[str1]].push_back(StrIndex[str2]);
Edge[StrIndex[str2]].push_back(StrIndex[str1]);
}
printf("Case #%d: ", ti);
bool ok=1;
for(int i=0;i<n;i++){
if(!dfs(0, 1)) {ok=0; break;}
}
puts(ok?"YES":"NO");
}
return 0;
}
一个技巧,不要全部算完再枚举各种color的个数,而是变量一直更着走,一直计数。cnt[1] cnt[2]
但是边界很恶心,一个是n<=1, 另一个是如果ans=n, 一定是有节的,而且是n-1, 1 所以特盘一下,因为n个离散点了
dfs用bool 类型表示当前dfs(i, c)是否可染色
int n, t, m, ans, u, v;
vector<int> Edge[maxn];
int color[maxn];
int cnt[3];//cnt[0], cnt[1], cnt[2]
bool dfs(int cur, int c){
color[cur]=c;
cnt[c]++;
for(auto i: Edge[cur]){
if(color[i]){
if(color[cur]==color[i]) return 0;
}
else if(!dfs(i, 3-c)) return 0;
}
return 1;
}
int main()
{
/*
#ifndef ONLINE_JUDGE
freopen ("in.txt" , "r" , stdin);
freopen ("out.txt" , "w" , stdout);
#endif
*/
t=getint();
while(t--){
n=getint(), m=getint();
//memset(a, 0 ,sizeof a);//0 means has connectinon
for(int i=1;i<=n;i++) Edge[i].clear();
memset(color, 0 ,sizeof color);
memset(cnt, 0, sizeof cnt);
for(int i=0;i<m;i++){
u=getint(), v=getint();
Edge[u].push_back(v);
Edge[v].push_back(u);
}
bool ok=1;
int ans=0;
for(int i=1;i<=n;i++){
if(color[i]) continue;
cnt[1]=cnt[2]=0;
if(!dfs(i, 1)){
ok=0;
break;
}
ans+=max(cnt[1] , cnt[2]);
}
if(ok && n>1){
if(ans==n) ans--;
cout<<ans<<" "<<n-ans<<endl;
}
else puts("Poor wyh");
}
return 0;
}