Codeforces1100 E. Andrew and Taxi(二分+有向图判环,拓扑序)
Posted live4m
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces1100 E. Andrew and Taxi(二分+有向图判环,拓扑序)相关的知识,希望对你有一定的参考价值。
题意:
解法:
显然二分答案mid,
将对边权>mid的边判环,如果有环则无解,
如果无环则一定有解,如何构造解?
只用>mid的边进行拓扑排序,记录每个点的拓扑序dfn[i],
对于<=mid的边,选择令拓扑序小的连向拓扑序大的,这样一定不会出现环.
code:
#include<bits/stdc++.h>
using namespace std;
const int maxm=1e5+5;
int head[maxm],nt[maxm],to[maxm],w[maxm],cnt;
int a[maxm],b[maxm],c[maxm];
int dfn[maxm],idx;
vector<int>temp;
int mark[maxm];
int vis[maxm];
int in[maxm];
int n,m;
int cir;
int ma;
void add(int x,int y,int z){
cnt++;nt[cnt]=head[x];head[x]=cnt;to[cnt]=y;w[cnt]=z;
}
void dfs(int x){
if(cir)return ;
vis[x]=1;
mark[x]=1;
for(int i=head[x];i;i=nt[i]){
int v=to[i];
if(w[i]<=ma)continue;
if(!mark[v]){
dfs(v);
}else{
cir=1;
}
}
mark[x]=0;
}
bool check(int mid){
cir=0;
for(int i=1;i<=n;i++){
vis[i]=0;
}
//
ma=mid;
for(int i=1;i<=n&&!cir;i++){
if(!vis[i]){
dfs(i);
}
}
return !cir;
}
void cal(int mid){
for(int i=1;i<=m;i++){
if(c[i]>mid){
in[b[i]]++;
}
}
//拓扑排序
queue<int>q;
for(int i=1;i<=n;i++){
if(!in[i]){
q.push(i);
}
}
while(q.size()){
int x=q.front();q.pop();
dfn[x]=++idx;//拓扑序
for(int i=head[x];i;i=nt[i]){
int v=to[i];
if(w[i]<=mid)continue;
if(in[v]>0){
in[v]--;
if(!in[v]){
q.push(v);
}
}
}
}
//
for(int i=1;i<=m;i++){
if(c[i]<=mid){
if(dfn[a[i]]>dfn[b[i]]){
temp.push_back(i);
}
}
}
}
void solve(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&a[i],&b[i],&c[i]);
add(a[i],b[i],c[i]);
}
int l=0,r=1e9;
int ans=0;
while(l<=r){
int mid=(l+r)/2;
if(check(mid)){
ans=mid,r=mid-1;
}else{
l=mid+1;
}
}
cal(ans);
printf("%d %d\\n",ans,temp.size());
for(auto i:temp){
printf("%d ",i);
}
}
signed main(){
solve();
return 0;
}
以上是关于Codeforces1100 E. Andrew and Taxi(二分+有向图判环,拓扑序)的主要内容,如果未能解决你的问题,请参考以下文章
codeforces 1100E-Andrew and Taxi
CF 1100E Andrew and Taxi(二分答案)