AT2046 Namori 圖論
正解:
解題報告:
傳送門!
首先看數據範圍可以發現要麽是棵樹要麽是個奇環要麽是個偶環
然後就分類討論分別看下這幾個情況
首先是棵樹的
首先可以想到樹的情況就是個二分圖,所以不妨把顏色重定義,讓奇數層的變成白色偶數層的變成黑色,然後就變成了,可以交換一個黑色和一個白色,求能否讓白的都變成黑的.黑的都變成白的
然後再賦個值,令黑色為-1白色為1
首先無解的情況很容易想到嘛,就是當黑色白色的點本來就不相等的時候顯然是布星的
然後繼續想,設f[i]:點i額外轉換的次數
顯然答案的下界是∑abs(f[i])
然後可以想到這個∑abs(f[i])顯然是可以達到的,有點兒像一個貪心的基礎題忘了叫什麽了,,,反正挺顯然的?
然後考慮有環的情況,這兒要分奇環偶環分開討論下
對於奇環,就相當於是連了同一奇偶性的兩個點,就是說本來正常交換是一個+1一個-1正好抵消,而這樣做就變成了都+1或者都+2,那就可以不保證黑色白色相等了,只要黑色白色的差值是偶數就可以通過這條邊抵消掉
所以可以發現這條邊的用處就是抵消差值,所以可以先算出差值,然後as+=差值/2,這時候這條邊的作用就用完了,剩下就當樹一樣處理就好
對於偶環,其實從大局來看就和樹是差不多的,就是假如現在已經在它們的lca之上了,那麽這條多余的鏈反正修改起來也是+1-1的所以馬油什麽影響
所以可以發現有影響的只是lca的子樹內部的,也就是那個環上的
可以考慮設這條多余的鏈上運輸了x次,然後可以發現,會改變的就左端點到lca會+=x,右端點到lca會-=x
然後被修改了的值列成式子就會變成,∑abs(t*f[i]-x),然後這兒t是±1,能get趴?就上面那個式子嘛
然後這個式子再仔細一看,小學奧數鴨,絕對值之和min就是取中位數的時候嘛
然後就做完啦啦啦!
放下代碼QAQ
#include<bits/stdc++.h> using namespace std; #define il inline #define ll long long #define rg register #defineView Codegc getchar() #define t(i) edge[i].to #define rp(i,x,y) for(rg int i=x;i<=y;++i) #define my(i,x,y) for(rg int i=x;i>=y;--i) #define e(i,x) for(rg int i=head[x];i;i=edge[i].nxt) const int N=1e5+10; int n,m,head[N],ed_cnt,sz[N],st,to,sum,as,top,stck[N],g[N]; struct ed{int to,nxt;}edge[N<<1]; bool jud; bool vis[N]; il int read() { rg char ch=gc;rg int x=0;rg bool y=1; while(ch!=‘-‘ && (ch>‘9‘ || ch<‘0‘))ch=gc; if(ch==‘-‘)ch=gc,y=0; while(ch>=‘0‘ && ch<=‘9‘)x=(x<<1)+(x<<3)+(ch^‘0‘),ch=gc; return y?x:-x; } il void ad(int x,int y){edge[++ed_cnt]=(ed){x,head[y]};head[y]=ed_cnt;} void dfs1(int x,int fa){e(i,x)if(t(i)^fa)if(sz[t(i)]){if(sz[t(i)]==sz[x])jud=1;st=x;to=t(i);}else sz[t(i)]=-sz[x],dfs1(t(i),x);} void dfs2(int x,int fa){vis[x]=1;e(i,x)if(t(i)^fa && !((x==st && t(i)==to) || (x==to && t(i)==st)))dfs2(t(i),x),sz[x]+=sz[t(i)],g[x]+=g[t(i)];return;} int main() { n=read();m=read();rp(i,1,m){int x=read(),y=read();ad(x,y);ad(y,x);}sz[1]=1;dfs1(1,0); rp(i,1,n)sum+=sz[i];if(!jud)if(sum)return printf("-1\n"),0; if(m==n)if(jud){if(sum&1)return printf("-1\n"),0;as+=abs(sum>>1);sz[st]-=(sum>>1);sz[to]-=(sum>>1);}else g[st]=1,g[to]=-1; dfs2(1,0); rp(i,1,n){if(g[i])stck[++top]=g[i]*sz[i];else as+=abs(sz[i]);} stck[++top]=0;sort(stck+1,stck+top+1);int mid=stck[(top+1)>>1]; rp(i,1,top)as+=abs(stck[i]-mid); printf("%lld\n",as); return 0; }
AT2046 Namori 圖論