結果
問題 |
No.2987 Colorful University of Tree
|
ユーザー |
|
提出日時 | 2025-05-24 18:30:24 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
WA
|
実行時間 | - |
コード長 | 8,756 bytes |
コンパイル時間 | 3,007 ms |
コンパイル使用メモリ | 213,236 KB |
実行使用メモリ | 41,024 KB |
最終ジャッジ日時 | 2025-05-24 18:30:40 |
合計ジャッジ時間 | 13,437 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | WA * 33 RE * 9 |
コンパイルメッセージ
main.cpp: In function ‘int main()’: main.cpp:49:9: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 49 | scanf("%d",&n); | ~~~~~^~~~~~~~~ main.cpp:53:12: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 53 | scanf("%d",&k); | ~~~~~^~~~~~~~~ main.cpp:57:15: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 57 | scanf("%d",&x); | ~~~~~^~~~~~~~~
ソースコード
#include<bits/stdc++.h> using namespace std; int n; int ans; int len[200005]; vector<pair<int,int> > D; int sum[200005]; vector<int> need[200005]; vector<int> E[200005]; vector<int> col[200005]; int qeta[400005]; int belone[200005]; int stb[200005]; vector<pair<int,int> > G[200005]; vector<int> self[200005]; int chk[200005]; vector<int> whe[200005]; bool check(int Q){// int tim=1; while(tim--){ for(int i=1;i<=Q;i++)sum[i]=0,need[i].clear(); for(int i=1;i<D.size();i++)swap(D[i],D[rand()%i]); for(int i=D.size()-1;i>=0;i--){ bool flg=false;// for(int j=1;j<=Q;j++){ if(sum[j]+D[i].first<=Q){ sum[j]+=D[i].first; flg=true;// need[j].push_back(D[i].second); belone[D[i].second]=j; break; } } if(!flg)break;// if(!i)return true; } } return false; } bool cmp(int a,int b){ return G[a].size()>G[b].size(); } int nxt[200005]; int find(int x){return nxt[x]==x?x:nxt[x]=find(nxt[x]);} int main(){ srand(time(0)); // freopen("city.in","r",stdin); // freopen("city.out","w",stdout); scanf("%d",&n); ans=ceil(sqrt(2*(n-1))); for(int i=1;i<=n;i++){ int k; scanf("%d",&k); len[i]=k; int x; for(int j=1;j<=k;j++){ scanf("%d",&x); whe[i].push_back(x+E[x].size()*n); E[x].push_back(i); } // printf("%lu\n",whe[i].size()); // return 0; ans=max(ans,k); D.push_back(make_pair(k,i)); } sort(D.begin(),D.end()); while(!check(ans))ans++; printf("%d\n",ans); // for(int i=1;i<=n;i++){ // printf("%d ",1); // for(int j=1;j<=len[i];j++)printf("%d ",1); // puts(""); // } for(int i=1;i<n;i++){//如果他自己连自己,考虑预先分配颜色给他就好了 int u=E[i][0]; int v=E[i][1]; if(belone[u]==belone[v]){ self[belone[u]].push_back(i); continue; } // printf("id=%d (%d,%d) %d -> %d\n",i,u,v,belone[u],belone[v]); G[belone[u]].push_back(make_pair(belone[v],i)); G[belone[v]].push_back(make_pair(belone[u],n+i)); } vector<int> id; for(int i=1;i<=ans;i++)id.push_back(i); int tim=1; while(tim--){ sort(id.begin(),id.end(),cmp); // return 0; //考虑对于每个色块,枚举一下邻接边,然后再随机枚举一个颜色,把他分配给他没出现的地方 //考虑每次选择的颜色,要求出现次数最多好了,然后分配完之后他的位置就可以随便占真是太方便了 //对于相等的就随机选 //不对,这个意思不就是,不管怎么样,都能分配出来,但是还是得按照度数排序,因为极端情况有可能需要用Q+1次,大概是这样 //然后对于每个点其实也不一定要很严格说度数怎么怎么分配,只要一个点往外分配,他自己的位置就一定会空出来,所以就没有问题 //我不应该这么早就定下那些自己指向自己的边应该怎么样选择。 for(int i=0;i<id.size();i++){ int now=id[i]; // cerr<<now<<'\n'; // printf("now=%d\n",now); // printf("i=%d now=%d\n",i,now); vector<int> D; // for(int j=1;j<=ans;j++){//对于一个颜色,只要对外有一点点就统计好了 // chk[j]=false; // } vector<int> ruozhi; for(int j=0;j<G[now].size();j++){ int v=G[now][j].first; int id=G[now][j].second; if(id>n){ if(qeta[id-n]){ ruozhi.push_back(qeta[id-n]); chk[qeta[id-n]]=now; } } else{ if(qeta[id+n]){ ruozhi.push_back(qeta[id+n]); chk[qeta[id+n]]=now; } } } sort(ruozhi.begin(),ruozhi.end()); if(ruozhi.size())D.push_back(ruozhi[0]); for(int i=1;i<ruozhi.size();i++){ if(ruozhi[i] xor ruozhi[i-1])D.push_back(ruozhi[i]); } // for(int j=1;j<=ans;j++){ // if(chk[j]){ // D.push_back(j); // } // } for(int j=1;j<D.size();j++){ swap(D[j],D[rand()%j]); } // printf("sizD=%lu sizG=%lu\n",D.size(),G[now].size()); // if(D.size())return 0; // puts("CLEAR!!"); for(int k=0;k<=G[now].size();k++)nxt[k]=k; for(int j=0;j<D.size();j++){ // return 0; int ncol=D[j]; // printf("ncol=%d\n",ncol); int k=find(0); while(k<G[now].size()){ int v=G[now][k].first; int id=G[now][k].second; if(qeta[id]){ k=find(k+1); continue; } // printf("k=%d id=%d\n",k,id); if(id>n){ if(qeta[id-n]==ncol){ k=find(k+1); continue; } qeta[id]=ncol; nxt[k]=k+1; break; } else{ if(qeta[id+n]==ncol){ k=find(k+1); continue; } qeta[id]=ncol; nxt[k]=k+1; break; } // if(k+1==G[now].size()){ // puts("error"); // } } } // if(i==0)return 0; D.clear(); int all=2*self[now].size(); for(int j=0;j<G[now].size();j++){ int v=G[now][j].first; int id=G[now][j].second; if(qeta[id])continue; all++; } // printf("i=%d\n",i); // puts("clear!"); for(int j=1;j<=ans&&D.size()<all;j++){ if(chk[j] xor now){ D.push_back(j); } } assert(D.size()==all); for(int j=1;j<D.size();j++){ swap(D[j],D[rand()%j]); } // printf("siz=%lu sizG=%lu sizself=%lu\n",D.size(),G[now].size(),self[]); int stb=0; for(int j=0;j<G[now].size();j++){ int v=G[now][j].first; int id=G[now][j].second; if(qeta[id])continue; qeta[id]=D[stb++]; } for(int j=0;j<self[now].size();j++){ int eid=self[now][j]; qeta[eid]=D[stb++]; assert(stb<D.size()); qeta[n+eid]=D[stb++]; } // puts("clear!"); // if(now==45)return 0; } // puts("CLEAR!!"); for(int i=1;i<=n;i++){ // printf("i=%d siz=%lu\n",i,whe[i].size()); printf("%d ",belone[i]); for(int j=0;j<whe[i].size();j++){ // printf("%d\n",whe[i][j]); printf("%d ",qeta[whe[i][j]]); } // printf("i=%d\n",i); puts(""); } } // puts("No Source!") //考虑这样都成功了! //现在要做的事情就是开始拆分,然后但是有问题就是,我要求一条边的两端给出的颜色不准相同 //考虑先不管这个事情,暴力分配一下颜色 //如果没有一条边链接两个一样的颜色那就很好了 //否则的话考虑进行交换,我们先把色块弄出来,然后把色块之间的边集弄出来 //考虑我先从一个色块开始搜索,直接对颜色进行标号 //然后往相邻色块走。 //当两个色块之间有多条边的时候可以轮换,我们把这样的边称为重边,重边随便给标号后就可以删除 //这也太麻烦,考虑我直接搜,往下搜的时候每条边分配一个当前颜色块没选过的颜色,下面也这么往上给? //给边新建一个点,那么新图上的边的一条边的颜色必须相同,同时每个边点还要满足一个点不能有相同颜色的限制 //考虑把缩点之后的图建出来,那么这样的话限制就变成了不准有两条共点的边取到同种颜色 //长得有点像最大独立集。 //考虑我先分配一个点的颜色,这样子持续增量构造 //度数从大到小开始分配,然后每次随机分配颜色,这样子重复做100次 // return 0; } /* 考虑相当于是把点分给 Q 个集合,使得每个集合的总度数不超过 Q,问最小的Q 极值不一定取得到,比较不权威 考虑我枚举一下这个Q,因为大概就是根号级别的,大不了多少,然后考虑怎么分能判断Q是否可行呢。 首先在根号n以上的点 尝试贪心一下,优先分大的 */