《济南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元的方程组。那么其实就是求每列的方程组解的个数。

但是比赛时并不会高斯消元,所以没什么头绪。

代码待补

posted @ 2020-12-29 14:55  levill  阅读(257)  评论(0编辑  收藏  举报