bzoj 2503 相框——思路
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2503
我也知道应该只关注度数。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=1005,M=50005; int n,m,deg[N],sum,ans; int main() { scanf("%d%d",&n,&m);int x,y; for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); deg[x]++;deg[y]++; sum+=(!deg[x])+(!deg[y]);//焊接 } for(int i=1;i<=n;i++) { if(deg[i]>1)ans+=deg[i]/2-1+(deg[i]&1);//烧熔 sum+=(deg[i]&1);//焊接 } printf("%d",ans+(sum>>1)); return 0; }
应该仔细读题,那个不用deg[ i ]/2 - 1 + (deg[ i ] & 1),一次就能焊好;
而且还没管不同连通块。
TJ:http://www.cnblogs.com/TSHugh/p/7617699.html
需要记一下一个连通块里有没有奇度数的点,因为对于没有的要手动熔断。这时要特判是不是只有一个连通块。
学习TJ代码:https://blog.csdn.net/PoPoQQQ/article/details/48031135
终于发现一次就能把一个点熔好了。还记录了一个连通块有没有被熔过。就因为一次也能顺便熔出两个奇度数点,所以对于没有奇度数点的连通块要通过这个判断是否需要再熔一次。
还学习了TJ的好写法:读入的时候不用区分0的端点什么的,++n就好了!仔细想一想是等价的。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=1005,M=5e4+5; int n,m,deg[N],fa[N],jd,ans,yf,cnt; bool tag[N],cz[N]; int find(int a){return fa[a]==a?a:fa[a]=find(fa[a]);} int main() { scanf("%d%d",&n,&m);int x,y; for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); if(!x)x=++n;if(!y)y=++n;//!!! deg[x]++;deg[y]++;fa[find(x)]=find(y); // if(!x&&!y)jd+=2; // else if(x&&y)deg[x]++,deg[y]++,fa[find(x)]=find(y); // else{ // jd++;if(x)deg[x]++;if(y)deg[y]++; // } } for(int i=1;i<=n;i++) { if(deg[i]&1)jd++,tag[find(i)]=1; if(deg[i]>2)ans++,cz[find(i)]=1;//记录cz!//一次就能熔好!!!!! if(deg[i]&&fa[i]==i)cnt++;//deg[i]!! } if(cnt==1&&!jd){printf("0\n");return 0;} for(int i=1;i<=n;i++) if(fa[i]==i&&!tag[i]&&cnt>1) { if(!cz[i])ans++; jd+=2;//&&cnt>1! } printf("%d\n",ans+(jd>>1)); return 0; }
再次学习(抄)了一遍。
别忘了到处判断deg[ i ]!!!别忘了把数组调大,赋 fa[ ] 的时候也要调大范围!
虽然A了可是一点也不高兴怎么办……
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=1005,M=5e4+5,Lm=1e5+1e3+5;; int n,m,deg[Lm],fa[Lm],jd,ans,cnt; bool tag[Lm],cz[Lm]; int find(int a){return fa[a]==a?a:fa[a]=find(fa[a]);} int main() { scanf("%d%d",&n,&m);int x,y; for(int i=1;i<=Lm-5;i++)fa[i]=i; for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); if(!x)x=++n;if(!y)y=++n;//!!! deg[x]++;deg[y]++;fa[find(x)]=find(y); // if(!x&&!y)jd+=2; // else if(x&&y)deg[x]++,deg[y]++,fa[find(x)]=find(y); // else{ // jd++;if(x)deg[x]++;if(y)deg[y]++; // } } for(int i=1;i<=n;i++) { if(deg[i]&1)jd++,tag[find(i)]=1; if(deg[i]>2)ans++,cz[find(i)]=1;//记录cz!//一次就能熔好!!!!! if(deg[i]&&find(i)==i)cnt++;//deg[i]!! } // if(cnt==1&&!jd){printf("0\n");return 0;} for(int i=1;i<=n;i++) if(deg[i]&&find(i)==i&&!tag[i]&&cnt>1)//deg[i]!!! { if(!cz[i])ans++; jd+=2;//&&cnt>1! } printf("%d\n",ans+(jd>>1)); return 0; }