1. 程式人生 > 實用技巧 >《濟南icpc補題》

《濟南icpc補題》

J:

可以發現,如果這樣構造,我們一共有60位,二分圖兩邊的最小點數必定 <= 50個,那麼我們每次都用少的那邊來做大的全集來構造,這樣位數就夠了。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int N = 5e4 + 5;
const int M = 1e5 + 5;
const LL Mod = 1e9 + 7;
#define pi acos(-1)
#define INF 1e18
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace
FASTIO{ inline LL read(){ LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } } using namespace FASTIO;
int n,a[105]; vector<int> G[105]; void dfs(int u,int fa) { a[u] = a[fa] ^ 1; for(auto v : G[u]) if(v != fa) dfs(v,u); } int le[105],ri[105],tot1 = 0,tot2 = 0; LL val[105]; //le 1111111110,ri 11111111101 int main() { n = read(); for(int i = 1;i < n;++i) { int x,y;x = read(),y = read(); G[x].push_back(y); G[y].push_back(x); } dfs(
1,0); for(int i = 1;i <= n;++i) { if(a[i] == 0) le[++tot1] = i; else ri[++tot2] = i; } if(tot1 > tot2) { swap(tot1,tot2); swap(le,ri); } for(int i = 1;i <= tot1;++i) { val[le[i]] = (1LL << 60) - 1; val[le[i]] ^= 1; val[le[i]] ^= (1LL << (i + 1)); } for(int i = 1;i <= tot2;++i) val[ri[i]] = 1; for(int i = 1;i <= tot1;++i) { for(auto v : G[le[i]]) { val[v] ^= (1LL << (i + 1)); } } for(int i = 1;i <= n;++i) printf("%lld%c",val[i],i == n ? '\n' : ' '); system("pause"); return 0; }
View Code

A:官方題解中討論了各種情況,比賽的時候也想了想但是覺得不好寫。

其實把數字展開後就會發現,兩邊每列之間是獨立的。

並且構成了n元的方程組。那麼其實就是求每列的方程組解的個數。

但是比賽時並不會高斯消元,所以沒什麼頭緒。

程式碼待補