T4 给定6个队伍,让分成两个不为空的小组。题很简单,但是有6个规则,逻辑判断很麻烦。这里学了一手,可以把所有解放入结构体,进行优先级排序,排序后的第一个就是最优解。
O(2^6 * log(2 ^ 6))
Code:
#includeusing namespace std; int cnt[10]; int a[10][5]; int n,m,k,T; int ans = 1; struct node{ int x; bool f1,f2,f3; //规则0、1、2 int dis; //人数差 bool f4; //左边人多 vector l; bool operator<(const node&rhs)const { if(f1 != rhs.f1) return f1 > rhs.f1; if(f2 != rhs.f2) return f2 > rhs.f2; if(f3 != rhs.f3) return f3 > rhs.f3; if(dis != rhs.dis) return dis < rhs.dis; if(f4 != rhs.f4) return f4 > rhs.f4; for(int i=0;i int t1 = l[i],t2 = rhs.l[i]; if(t1 != t2) return t1 < t2; } } }v[100]; void solve() { n = 6; for(int i=0;i >cnt[i]; int t = 0; for(int i=0;i for(int j=0;j<3;++j) scanf("%1d",&a[i][j]); if(a[i][0]) t++; } if(t < 2) { cout<<"GG"; return ; } for(int i=0;i<(1<<6);++i) { v[i].x = i; v[i].f1 = v[i].f2 = v[i].f3 = v[i].f4 = 0; int x = i; vector l,r; for(int i=0;i if(!cnt[i]) continue; if(x>>i&1) l.push_back(i); else r.push_back(i); } if(!l.size() || !r.size()) continue; v[i].l = l; bool f1 = 0,f2 = 0,f3 = 0,f4 = 0,f5 = 0,f6 = 0; int sum1 = 0,sum2 = 0; for(int i=0;i int x = l[i]; if(a[x][0]) f1 = 1; if(a[x][1]) f2 = 1; if(a[x][2]) f3 = 1; sum1 += cnt[x]; } for(int i=0;i int x = r[i]; if(a[x][0]) f4 = 1; if(a[x][1]) f5 = 1; if(a[x][2]) f6 = 1; sum2 += cnt[x]; } if(f1 && f4) v[i].f1 = 1; if(f2 && f3 && f5 && f6) v[i].f2 = 1; if(f3 && f6) v[i].f3 = 1; v[i].dis = abs(sum1-sum2); if(sum1 > sum2) v[i].f4 = 1; else v[i].f4 = 0; } sort(v,v+64); int x = v[0].x; vector l,r; for(int i=0;i if(!cnt[i]) continue; if(x>>i&1) l.push_back(i+1); else r.push_back(i+1); } for(int i=0;i if(i) cout<<" "; cout< if(i) cout<<" "; cout< solve(); return 0; }
T5
题意:
设 G=(V,E) 是一个无向图,如果顶点集合 V 可分割为两个互不相交的子集 (A,B),并且每条边 (i,j)∈E 的两个端点 i 和 j 分别属于这两个不同的顶点子集,则称图 G 为一个二分图。
现在给定一棵树 T,要求选择树中两个没有边相连的结点 i 和 j,使得将无向边 (i,j) 加进 T 后能够构成二分图。你的任务是计算满足这个要求的选择方案有多少种。
思路: 首先,给定的树一定是一个二分图,因为无环,每条边两边连的点黑白染色即可。那么,我们就可以先对给定的树进行黑白染色,假设黑色节点有x个,白色节点则是剩余的n-x个。所有黑色节点连向白色节点,最多有x*(n-x),原来有n-1条边,方案就是二者之差,这些边都可以分别加一次。
O(n)
Code:
#includeusing namespace std; const int N = 1e6+10; vector va[N]; int n,m,k,T; bool vis[N]; void dfs(int cur,int fa,bool st) { vis[cur] = st; for(int i=0;i int j = va[cur][i]; if(j==fa) continue; dfs(j,cur,!st); } } void solve() { cin>>n; for(int i=0;i int x,y; cin>>x>>y; va[x].push_back(y),va[y].push_back(x); } dfs(1,0,1); int l = 0,r = 0; for(int i=1;i<=n;++i) { if(vis[i]) l++; } r = n-l; long long ans = 1ll*l*r; ans -= (n-1); cout< solve(); return 0; }



