CodeForces 455C (貪心,並查集)
阿新 • • 發佈:2019-01-03
題意:
給出一個n個點m條邊的森林,q次詢問,第一種詢問要求輸出一個點所在樹的直徑,第二種詢問要求合併兩個點所在的樹。
思路:
先將初始的森林中各個樹的直徑求出來,然後用並查集維護。兩樹合併時,設直徑分別為len1,len2,新樹直徑為max(len1,len2,(len1/2)+(len2/2)+(len1%2)+(len2%2)+1),即兩顆舊樹的直徑,兩顆舊樹直徑的一半向上取整加一,中的較大值。
優化上可以用並查集路徑壓縮+啟發式合併,輸入掛。
程式碼:
#include <iostream> #include <iomanip> #include <algorithm> #include <cstring> #include <cctype> #include <cstdlib> #include <cstdio> #include <cmath> #include <ctime> #include <map> #include <list> #include <set> #include <stack> #include <queue> #include <string> #include <sstream> #define pb push_back #define X first #define Y second #define ALL(x) x.begin(),x.end() #define INS(x) inserter(x,x.begin()) #define pii pair<int,int> #define qclear(a) while(!a.empty())a.pop(); #define lowbit(x) (x&-x) //#define sd(n) scanf("%d",&n) #define sdd(n,m) scanf("%d%d",&n,&m) #define sddd(n,m,k) scanf("%d%d%d",&n,&m,&k) #define mst(a,b) memset(a,b,sizeof(a)) #define cout3(x,y,z) cout<<x<<" "<<y<<" "<<z<<endl #define cout2(x,y) cout<<x<<" "<<y<<endl #define cout1(x) cout<<x<<endl #define IOS std::ios::sync_with_stdio(false) #define SRAND srand((unsigned int)(time(0))) typedef long long ll; typedef unsigned long long ull; typedef unsigned int uint; using namespace std; const double PI=acos(-1.0); const int INF=0x3f3f3f3f; const ll mod=998244353; const double eps=1e-8; const int maxn=300005; const int maxm=10005; template<class T> inline bool sd(T &ret){ char c; int sgn; if(c=getchar(),c==EOF)return 0; while(c!='-'&&(c<'0'||c>'9'))c=getchar(); sgn=(c=='-')?-1:1; ret=(c=='-')?0:(c-'0'); while(c=getchar(),c>='0'&&c<='9')ret=ret*10+(c-'0'); ret*=sgn; return 1; } inline void out(int x){ if(x>9)out(x/10); putchar(x%10+'0'); } int n,m,q; vector<int>maps[maxn]; int fa[maxn]; int rk[maxn]; inline void init(){ for(int i=0;i<=n;i++){ fa[i]=i; rk[i]=1; } } inline int findfa(int x){ return fa[x]==x?x:fa[x]=findfa(fa[x]); } inline void meg(int a,int b){ int f1,f2; f1=findfa(a); f2=findfa(b); if(rk[f1]<rk[f2]){ fa[f1]=f2; rk[f2]+=rk[f1]; }else{ fa[f2]=f1; rk[f1]+=rk[f2]; } return ; } int lens[maxn]; bool vis[maxn]; int maxlen=0; int mark=-1; inline void dfs(int u,int d){ vis[u]=1; if(d>maxlen){ maxlen=d; mark=u; } for(int i=0;i<maps[u].size();i++){ int v=maps[u][i]; if(!vis[v]){ dfs(v,d+1); } } vis[u]=0; } inline void callens(int now){ maxlen=0; mark=-1; dfs(now,0); dfs(mark,0); lens[now]=maxlen; } void solve() { sd(n); sd(m); sd(q); init(); for(int i=0;i<m;i++){ int u,v; sd(u); sd(v); maps[u].pb(v); maps[v].pb(u); meg(u,v); } mst(lens,0); mst(vis,0); for(int i=1;i<=n;i++){ int now=findfa(i); if(lens[now]==0){ callens(now); } } for(int qq=0;qq<q;qq++){ int op,u,v; sd(op); if(op==1){ sd(u); out(lens[findfa(u)]); putchar('\n'); }else{ sd(u); sd(v); if(findfa(u)==findfa(v))continue; int len1,len2,len3; len1=lens[findfa(u)]; len2=lens[findfa(v)]; len3=(len1>>1)+(len2>>1)+(len1&1)+(len2&1)+1; meg(u,v); lens[findfa(u)]=max(len1,max(len2,len3)); } } return ; } int main() { #ifdef LOCAL freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); #else // freopen("","r",stdin); // freopen("","w",stdout); #endif solve(); return 0; }