北京師範大學第十六屆程序設計競賽決賽 F 湯圓防漏理論
阿新 • • 發佈:2018-05-26
lap 示例 names col copy AC www. 總結 tor
空間限制:C/C++ 32768K,其他語言65536K
64bit IO Format: %lld
編號,有m對湯圓互相接觸,用xi, yi, zi表示編號為xi和yi的兩個湯圓互相接觸,粘(nián)度為zi。
湯圓當然是越軟越好吃,但是ghc的廚藝只允許把所有湯圓煮成同樣的硬度。那麽,湯圓的硬度最小可以是多少,可以滿足吃的過程中,存在一種夾湯圓的順序,使得沒有湯圓會被粘(zhān)漏呢?
註意:
不考慮湯圓的重力作用;
不能同時夾多個湯圓;
吃完湯圓一定要喝點湯。 ≠ yi, 1 ≤ zi ≤ 1000000),
同一對湯圓不會出現兩次。
鏈接:https://www.nowcoder.com/acm/contest/117/F
來源:牛客網
空間限制:C/C++ 32768K,其他語言65536K
64bit IO Format: %lld
題目描述
ghc很喜歡吃湯圓,但是湯圓很容易被粘(zhān)漏。
根據多年吃湯圓經驗,ghc總結出了一套湯圓防漏理論:
互相接觸的湯圓容易粘(zhān)在一起,並且接觸面積不同,粘(zhān)在一起的粘(nián)度也不同。
當ghc要夾起一個湯圓時,這個湯圓和現在碗裏與這個湯圓接觸的所有湯圓之間的粘(nián)度的和,如果大於湯圓的硬度,這個湯圓就會被粘(zhān)漏。
今天ghc又要煮湯圓啦,今天要煮n個湯圓,並且擺盤的方法已經設計好:
湯圓按照
湯圓當然是越軟越好吃,但是ghc的廚藝只允許把所有湯圓煮成同樣的硬度。那麽,湯圓的硬度最小可以是多少,可以滿足吃的過程中,存在一種夾湯圓的順序,使得沒有湯圓會被粘(zhān)漏呢?
註意:
不考慮湯圓的重力作用;
不能同時夾多個湯圓;
吃完湯圓一定要喝點湯。
輸入描述:
第一行是一個正整數T(≤ 5),表示測試數據的組數,
對於每組測試數據,
第一行是兩個整數n,m(1≤ n,m≤ 100000),
接下來m行,每行包含三個整數xi, yi, zi(1≤ xi, yi ≤ n, xi
同一對湯圓不會出現兩次。
輸出描述:
對於每組測試數據,輸出一行,包含一個整數,表示湯圓硬度的最小值。示例1
輸入
復制1 4 6 1 2 2 1 3 2 1 4 2 2 3 3 2 4 3 3 4 5
輸出
復制6
法一:直接算
#include<bits/stdc++.h> using namespace std; const int N = 1e5 + 5; using LL = long long; using P = pair<LL, int>; LL cnt[N]; int n, m;set<P> edge[N]; priority_queue<P, vector<P>, greater<P> > Q; void Work() { LL ans = 0; for(int i = 1; i <= n; i++) { Q.push({cnt[i], i}); } while(!Q.empty()) { auto tmp = Q.top(); Q.pop(); if(tmp.first != cnt[tmp.second]) continue; int u = tmp.second; ans = max(ans, tmp.first); for(auto p : edge[u]) { int v = p.second; cnt[v] -= p.first; edge[v].erase({p.first, u}); Q.push({cnt[v], v}); } } cout << ans << endl; } int main() { int T; cin >> T; while(T--) { cin >> n >> m; for(int i = 1; i <= n; i++) { edge[i].clear(); cnt[i] = 0; } int u, v, w; for(int i = 1; i <= m; i++) { cin >> u >> v >> w; cnt[u] += w; cnt[v] += w; edge[u].insert({w, v}); edge[v].insert({w, u}); } Work(); } }
#include<cstdio> #include<cmath> #include<set> #include<queue> #include<algorithm> #include<iostream> #include<cstring> #include<vector> using namespace std; #define ll long long #define N 100000 #define mod 1000000007 #define pa pair<ll,ll> vector<pa>g[N+5]; set<pa>p; ll sum[N+5]; //表示編號為i的人的粘稠度綜合 bool vis[N+5]; //去重 int main() { int i,j,t,q,n,m,a,b,w,x; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(i=1;i<=n;i++) //p不需要清了,本來就是空的 { g[i].clear(); sum[i]=0; vis[i]=false; } while(m--) { scanf("%d%d%d",&a,&b,&w); g[a].push_back(pa(b,w)); g[b].push_back(pa(a,w)); //將a,b連接起來 sum[a]+=w; sum[b]+=w; } for(i=1;i<=n;i++) p.insert(pa(sum[i],i)); //將數據輸入到set ll maxd=0; while(!p.empty()) //貪心 { set<pa>::iterator it=p.begin(); pa now= *it; //now.first表示他的粘稠度,now,second表士坐標 p.erase(*it); maxd=max(now.first,maxd); // printf("%lld now.first=%lld\n",maxd,now.first); x=now.second; vis[x]=true; //標記 //第一步,刪除權值的邊 for(i=0;i<g[x].size();i++) { pa l=g[x][i]; //為了理解,再寫下,l.first是x對應的邊 if(vis[l.first]) continue; p.erase(pa(sum[l.first],l.first)); sum[l.first]-=l.second; p.insert(pa(sum[l.first],l.first)); } } printf("%lld\n",maxd); } return 0; }View Code
題解: 二分硬度,拓撲排序判斷是否可行 代碼: #include<bits/stdc++.h> using namespace std; #define ll long long const int maxn=1e5+7; struct node { int to;ll cost; }; vector<node>p[maxn]; queue<int>P; ll a[maxn],zz[maxn]; bool vis[maxn]; int n,m,xx[maxn],yy[maxn]; bool pp(ll x) { for(int i=0;i<=n;i++)p[i].clear(); memset(a,0,sizeof(a)); for(int i=0;i<m;i++) { node e;e.to=yy[i];e.cost=zz[i]; p[xx[i]].push_back(e); e.to=xx[i]; p[yy[i]].push_back(e); a[xx[i]]+=zz[i]; a[yy[i]]+=zz[i]; } int ans=0;memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++) { if(!vis[i]&&a[i]<=x) { ans++; vis[i]=1; for(int j=0;j<p[i].size();j++) { int to=p[i][j].to;ll z=p[i][j].cost; a[to]-=z; if(!vis[to]&&a[to]<=x)P.push(to),ans++,vis[to]=1; } } } while(!P.empty()) { int v=P.front();P.pop(); for(int i=0;i<p[v].size();i++) { node e=p[v][i]; a[e.to]-=e.cost; if(!vis[e.to]&&a[e.to]<=x)P.push(e.to),ans++,vis[e.to]=1; } } if(ans==n)return 1; return 0; } int main() { int T;scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=0;i<m;i++) { int x,y;ll z; scanf("%d%d%lld",&x,&y,&z); xx[i]=x;yy[i]=y;zz[i]=z; } ll l=-1,r=1e18; while(r-l>1) { ll mid=(l+r)/2; if(pp(mid))r=mid; else l=mid; } printf("%lld\n",r); } return 0; }
北京師範大學第十六屆程序設計競賽決賽 F 湯圓防漏理論