先是F题,一开始我做的这个题,一开始的思路是对的,但是判断是否存在环的时候我就想到kruskal算法的思想,如果这个集中有成环的就把这个根节点标记,然后在判断就可以了,但是不对,因为并查集合并的时候会改变最初的数字,然后就看着队里一个大佬,做的,就是存图,然后在判断每一个集是否成环,错误代码:
#include<bits/stdc++.h> using namespace std; #define LL long long int s[1005],vis[1005],vis1[1005]; int find(int x) { return s[x]==x?s[x]:s[x]=find(s[x]); } int main() { int t; cin>>t; for(int k=1;k<=t;k++) { int n,m; cin>>n>>m; for(int i=1;i<=n;i++)s[i]=i,vis[i]=vis1[i]=0; for(int j=0;j<m;j++) { int a,b; cin>>a>>b; vis1[a]=vis1[b]=1; int x=find(a),y=find(b); if(x!=y)s[x]=y; else { vis[x]++; } } int n1=0,n2=0; for(int i=1;i<=n;i++) { //cout<<i<<" "<<vis1[i]<<endl; if(vis1[i]==0)continue; if(s[i]==i)n1++; if(vis[i]==1)n2++; } printf("Night sky #%d: %d constellations, of which %d need to be fixed. \n\n",k,n1,n2); } }
AC代码:
#include<bits/stdc++.h> using namespace std; #define LL long long int s[1005],vis[1005],vis1[1005]; int find(int x) { return s[x]==x?s[x]:s[x]=find(s[x]); } vector<int>p[1005]; int cnt[1005]; int flag; void solve(int i,int pre) { cnt[i] ++; if(cnt[i] >= 2) { flag = 1; return; } for(int j=0;j<p[i].size();j++) { if(p[i][j]==pre)continue; solve(p[i][j],i); } } int main() { int t; cin>>t; for(int k=1;k<=t;k++) { int n,m; cin>>n>>m; for(int i=1;i<=n;i++){ s[i]=i,vis[i]=vis1[i]=0,p[i].clear(); cnt[i] = 0; } for(int j=0;j<m;j++) { int a,b; cin>>a>>b; p[a].push_back(b); p[b].push_back(a); vis1[a]=vis1[b]=1; int x=find(a),y=find(b); if(x!=y)s[x]=y; } int n1=0,n2=0; for(int i=1;i<=n;i++) { //cout<<i<<" "<<vis1[i]<<endl; if(vis1[i]==0)continue; if(s[i]==i) { n1++; flag=0; solve(i,0); n2 += flag; } } printf("Night sky #%d: %d constellations, of which %d need to be fixed. \n\n",k,n1,n2); } }
最离谱的是G题,一开始也是我做的,思路也对,其他的都对,但是没特判1 的情况,导致错了很多,最离谱的是我的队友都给我说特判一的情况了,但是我又给否决了...认真思考..