傳code
說明:
$SUM[i]$為城市$i$連出去的道路數字總和
可以注意到首都是和所有城市相連的
所以一定可以讓$SUM[1]$ (首都的數字總和) 最大,有個方法是把數字$(M-N+2)\sim(M)$分配給連到首都的道路
先不用確定$(M-N+2)\sim(M)$要分配給哪些道路
我們可以先把其他城市之間的道路隨便給一個數字
然後算好每個城市 (不包括首都$1$) 連出去的道路數字總和
將這些城市依照目前的道路數字總和排序
假設排序後的城市為$\{c_{1},c_{2},c_{3},...,c_{N-1}\}$
發現了嗎?
對於城市$c_{i}$,將$c_{i}$和首都相連的道路的數字設定成$M-N+1+i$
可以發現,我們可以保證$SUM[c_{i}]<SUM[c_{i+1}]<SUM[1],\forall i\in [1,N-2]$
時間複雜度:$O(M+N\log N)$
code:
#include<cstdio> #include<cassert> #include<vector> #include<algorithm> using namespace std; struct Edge { int a,b,val; Edge(){} Edge(const int _a,const int _b,const int _val):a(_a),b(_b),val(_val){} }; vector<Edge>EDGE; vector<int>ET[1000]; int N,M,SUM[1000]; int main() { freopen("flights.in","r",stdin); freopen("flights.out","w",stdout); // freopen("in.txt","r",stdin); while(scanf("%d%d",&N,&M)==2) { if(N==0&&M==0)break; for(int i=0;i<N;i++)ET[i].clear(); EDGE.clear(); for(int i=0,a,b;i<M;i++) { scanf("%d%d",&a,&b),a--,b--; EDGE.push_back(Edge(a,b,0)); ET[a].push_back(i),ET[b].push_back(i); } for(int i=0;i<N;i++)SUM[i]=0; int count=0; for(int i=0;i<M;i++) { Edge &e=EDGE[i]; if(e.a!=0&&e.b!=0) { count++; e.val=count; SUM[e.a]+=count,SUM[e.b]+=count; } } assert((int)ET[0].size()==N-1&&count+(N-1)==M); vector<int>order; for(int i=1;i<N;i++)order.push_back(i); sort(order.begin(),order.end(),[](const int a,const int b)->bool{return SUM[a]<SUM[b];}); static int eis[1000]; for(int i=0;i<N-1;i++)eis[max(EDGE[ET[0][i]].a,EDGE[ET[0][i]].b)]=ET[0][i]; for(const int i:order) { Edge &e=EDGE[eis[i]]; count++; e.val=count; assert(e.a==0||e.b==0); SUM[e.a]+=count,SUM[e.b]+=count; } assert(count==M); puts("Yes"); for(int i=0;i<M;i++) { if(i)putchar(' '); printf("%d",EDGE[i].val); } puts(""); sort(SUM,SUM+N); for(int i=1;i<N;i++)assert(SUM[i-1]<SUM[i]); } return 0; }
沒有留言:
張貼留言
歡迎留言或問問題~
若您的留言中包含程式碼,請參考這篇
如果留言不見了請別慌,那是因為被google誤判成垃圾留言,小莫會盡快將其手動還原
注意:只有此網誌的成員可以留言。