洛谷P1525 关押罪犯(二分图+二分法+思维)
题目链接:https://www.luogu.com.cn/problem/P1525
题目解法:这个题很不错,是个思维题。因为换个问法就是,题目要求你问二分图同组内最大2点间花费。那么其实一个很不错的想法就是二分框定mid,我们保证大于mid的边能构建成二分图。这个时候就需要去找所谓mid的封顶值了。因为符合线性增大原理,所以可以二分来解决找mid。大概整体意思就是一般图里面扣最大二分图吧。
#include<bits/stdc++.h> #define ll long long #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define endl '\n' #define eps 0.000000001 #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const ll inf=0x3f3f3f3f3f3f3f3f; const int mod=1e9+7; const int maxn=1e5+5; int tot,head[maxn]; struct E{ int to,next,w; }edge[maxn<<1]; void add(int u,int v,int w){ edge[tot].to=v; edge[tot].w=w; edge[tot].next=head[u]; head[u]=tot++; } int n,m; bool bfs(int mid){ queue<int> q;int col[maxn]={0}; rep(i,1,n){ if(!col[i]){ q.push(i);col[i]=1; while(!q.empty()){ int now=q.front();q.pop(); for(int i=head[now];i!=-1;i=edge[i].next){ int v=edge[i].to,w=edge[i].w; if(w>=mid){ if(!col[v]){ col[v]=3-col[now]; q.push(v); } else if(col[v]==col[now]){ return false; } } } } } } return true; } int main(){ cin>>n>>m;mem(head,-1); int L=0,R=0; rep(i,1,m){ int u,v,w;cin>>u>>v>>w; R=max(R,w); add(u,v,w);add(v,u,w); } while(R>L){ int mid=(L+R)>>1; if(bfs(mid)) R=mid; else L=mid+1; } if(L-1>=0)cout<<L-1<<endl; else puts("0"); }
前ICPC算法竞赛退役选手|现摸鱼ing