SDUT 2022 Summer Individual Contest - 6 (补题)
题目链接:
Brexit - Kattis brexit - Virtual Judge (vjudge.net)
题意:给出c,p,x,l代表给出c个部落,有p个联盟关系,x代表目标部落,l是最先脱离的部落。接下来有p行,每行输入a,b代表a,b有联盟关系;
部落脱离部条件是建立联盟的伙伴>=一半的脱离。
询问:x最后如果能脱离联盟输出leave,否则输出stay;
分析:链式前向星+bfs或vector+bfs跑一遍就可以
链式前向星+bfs:
#include <bits/stdc++.h> #define endl '\n' #define x first #define y second #define PI acos(-1) #define SugarT ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII; const int N=2e5+10; const int M=1e6+10; const int INF=0x3f3f3f3f; const int mod=1e9+7; const double eps = 1e-6; int c,p,x,l; int h[N],e[M],ne[M],idx; int cnt[N],now[N]; bool st[N]; void add(int a,int b) { e[idx]=b,ne[idx]=h[a],h[a]=idx++; } void solve() { memset(h,-1,sizeof h); cin >> c >> p >> x >> l; while(p--) { int a,b; cin >> a >> b; add(a,b); add(b,a); cnt[a]++,cnt[b]++;//记录每个国家的贸易国总数 now[a]++,now[b]++;//记录每个国家现存的贸易国数量 } queue<int> q; q.push(l); while(q.size()) { auto t=q.front(); q.pop(); if(st[t])continue; st[t]=true; for(int i=h[t];i!=-1;i=ne[i]) { auto j=e[i]; if(st[j])continue;//如果已经被标记过就往下找 now[j]--; if(now[j]*2<=cnt[j])q.push(j);//判断这个国家是否需要退出 } } if(!st[x])cout << "stay" << endl; else cout << "leave" << endl; } int main() { SugarT int T=1; //cin >> T; while(T--) solve(); return 0; }
vector+bfs:
#include <bits/stdc++.h> #define endl '\n' #define x first #define y second #define PI acos(-1) #define SugarT ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII; const int N=2e5+10; const int M=1e6+10; const int INF=0x3f3f3f3f; const int mod=1e9+7; const double eps = 1e-6; int c,p,x,l; vector<int> v[N]; int cnt[N],now[N]; bool st[N]; void solve() { cin >> c >> p >> x >> l; while(p--) { int a,b; cin >> a >> b; v[a].push_back(b); v[b].push_back(a); cnt[a]++,cnt[b]++;//记录每个国家的贸易国总数 now[a]++,now[b]++;//记录每个国家现存的贸易国数量 } queue<int> q; q.push(l); while(q.size()) { auto t=q.front(); q.pop(); if(st[t])continue; st[t]=true; for(int i=0;i<v[t].size();i++) if(st[v[t][i]])continue;//如果已经被标记过就往下找 else{ now[v[t][i]]--; if(now[v[t][i]]*2<=cnt[v[t][i]])//判断这个国家是否需要退出 q.push(v[t][i]); } } if(!st[x])cout << "stay" << endl; else cout << "leave" << endl; } int main() { SugarT int T=1; //cin >> T; while(T--) solve(); return 0; }
题目链接:
题意:一张城市网,有n个城市,m条高速公路,只有城里有充电站、公路上没有充电站,充电时间不计,汽车电池有多少电量就只能走多少路,男人每天需要在1号家和m好公司之间奔波,男人为了省钱需要买尽可能小的汽车电池,女人为了让男人尽快的回家让男人走最近的路。经过妥协,男人必须走不超过最短路长度x%的路,在这基础上男人能买的最小电池为多少?
分析:跑一遍Dijkstra将最短距离算出来,所以题目要求的最短路的长度不能超过(1+%x)*dist[n],所以二分电瓶容量,电瓶容量=最短路中道路最大的权值,所以当电瓶容量为x时,图里面权值大于x的边可以不用进行考虑。
#include <bits/stdc++.h> #define endl '\n' #define x first #define y second #define int long long #define PI acos(-1) #define SugarT ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII; const int N=1e5+10; const int M=1e6+10; const int INF=0x3f3f3f3f; const int mod=1e9+7; const double eps = 1e-6; int n,m,x; int h[N],e[M],ne[M],w[M],idx; int dist[N]; bool st[N]; struct node { int x; int y; }; struct cmp { bool operator() (const node &a,const node &b) const { return a.x>b.x; } }; void add(int a,int b,int c) { e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++; } int Dijkstra(int maxv)//maxv为允许出现的最大边长权值 { memset(dist,0x3f,sizeof dist); memset(st,false,sizeof st); dist[1]=0; priority_queue<node,vector<node>,cmp> q; q.push({0,1}); while(q.size()) { auto t=q.top(); q.pop(); int dis=t.x,ver=t.y; if(st[ver])continue; st[ver]=true; for(int i=h[ver];i!=-1;i=ne[i]) { auto j=e[i]; if(w[i]<=maxv)//只有小于限定权值大小的边才能进行迭代 { if(dist[j]>dist[ver]+w[i]) { dist[j]=dist[ver]+w[i]; q.push({dist[j],j}); } } } } return dist[n]; } void solve() { memset(h,-1,sizeof h); int maxs=-1; cin >> n >> m >> x; while(m--) { int a,b,c; cin >> a >> b >> c; maxs=max(maxs,c); add(a,b,c); add(b,a,c); } int res=Dijkstra(INF); double sum=res*1.0*(1.0+x*1.0/100);//允许出现的最短路最大值 //cout << sum << endl; int l=0,r=maxs; while(l<r) { int mid=l+r>>1; if(Dijkstra(mid)*1.0>sum)l=mid+1; else if(Dijkstra(mid)*1.0<sum)r=mid; else { cout << mid << endl; return; } } cout << l << endl; } signed main() { SugarT int T=1; //cin >> T; while(T--) solve(); return 0; }