G Greetings Souvenir
再更新一下,造了一些hack数据对拍,拿了三份代码对拍,给出几份hack数据
输出彼此之间都有一致的数据也有不一致的,说明至少四支队伍可以hack掉三只队伍!!!!
6
1 2 1 2 5
6 5 2 1 2 3
顶不住也给我顶:6
空白:5
吃顿好的:6
ContestinSurgery :段错误
6
6 4 5 2 1
3 1 6 2 5 4
顶不住也给我顶:4
空白:6
吃顿好的:6
ContestinSurgery :段错误
8
1 2 2 2 2 1 7
3 2 7 3 2 3 5 1
顶不住也给我顶:6
空白:6
吃顿好的:8
ContestinSurgery :段错误
网络流(不会) or 真正理解匈牙利算法给出一个也许正确的做法,因为它确实AC了
(应该是假算法了,就是数据弱了让我这个渣渣跑过去了)
这里建出来的二分图的特殊性质就是,越相邻的两个节点的bitset越相似,一个节点的父节点和子节点至多有两位不同(父节点颜色对应的值增加上了该颜色),也许导致这个算法的正确几率显著提升?或者完全正确?
这里匈牙利是n^2的,做了个(错误的)优化,每个左部点会记录已经匹配到的最小右部点
可以发现复杂度是o(边数)的
然而这样就假了(不是图论选手啊我),但是他就是AC了,也许建出来的图具有有某些性质???,也许数据弱了?
给出一个图论队友给的hack数据来hack匹配部分,这里mex应该是4,输出了3
#include<bits/stdc++.h> using namespace std; #define ul unsigned long const int maxn=32; bitset<maxn> b[maxn]; int c[maxn],n; int p[maxn]; int r[maxn]; int find(int x){ for(int i=r[x]+1;i<=n;i++){ r[x]=i; if(!b[i][x])continue; if(!p[i]||find(p[i])){ p[i]=x; return 1; } } return 0; } int main(){ ios::sync_with_stdio(0);cin.tie(0); n=3; b[1][1]=1; b[1][2]=1; b[2][1]=1; b[2][2]=1; b[2][3]=1; b[3][1]=1; int ans=1; for(int i=1;i<n;i++){ if(find(i))ans++; else break; } cout<<ans<<endl; }
题意:n个点的一棵树,第i个节点有颜色ci,每个节点可以分配一个任意的值di,ei=子树内颜色为di的个数*di,求mex(e1,e2...en)的最大值
思路,n^2预处理出每个节点的可能值,用bitset储存,将节点的所有可能值1到(n-1)看做左部,节点1到n看做右部,n^2做类似匈牙利匹配(暴力匹配),因为mex函数的集合要求数是连续的,所以我们逐个节点依次匹配,直到失配,总复杂度(n^2),优于标程,但是还是跑了6.8秒。
其中mex函数中的0始终可以分配给一个数,所以只要最后答案不超过n就行啦
预处理bitset表示的二分图如果多个log很容易T,用map TLE妥妥的,改成vector就AC了。
#include<bits/stdc++.h> using namespace std; #define ul unsigned long // const int maxn=32; const int maxn=20032; vector<int> e[maxn]; bitset<maxn> b[maxn]; int c[maxn],n; void dfs(int u,vector<pair<int,int> > &mp){ vector<pair<int,int> > now; now.push_back({c[u],1}); for(auto &v:e[u]){ dfs(v,now); } int tp[n+1]={}; for(auto &it:mp){ tp[it.first]=it.second; } for(auto &it:now){ int tmp=it.first*it.second; if(tmp<n)b[u].set(tmp); tp[it.first]+=it.second; } mp.clear(); for(int i=0;i<=n;i++){ if(tp[i]){ mp.push_back({i,tp[i]}); } } } int p[maxn]; int r[maxn]; int find(int x){ for(int i=r[x]+1;i<=n;i++){ r[x]=i; if(!b[i][x])continue; if(!p[i]||find(p[i])){ p[i]=x; return 1; } } return 0; } int main(){ ios::sync_with_stdio(0);cin.tie(0); cin>>n; for(int i=2;i<=n;i++){ int tmp;cin>>tmp; e[tmp].push_back(i); } for(int i=1;i<=n;i++){ cin>>c[i]; } vector<pair<int,int> > now; dfs(1,now); int ans=1; for(int i=1;i<n;i++){ if(find(i))ans++; else break; } cout<<ans<<endl; }