习题:Ralph and Mushrooms(拓扑)

题目

传送门

思路

考虑环的一个性质,如果强行断一条边,再跑拓扑,那么对于这条链上一定有\(id_u<id_v\),其中v的深度比u大

对于断的那条边的两个节点,一定有\(id_u>id_v\)

对于题目本身而言,单调性是显然的

考虑二分一个分界点mid,把边权>=mid的建图,如果满足题意,那么一定是一个DAG,通过二分,我们就可以求出最小的最大值

再者考虑构造,构造其实就按照上面提到的环的性质进行构造即可

代码

#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;    
namespace IO
{
    void read(int &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void write(int x)
    {
        if(x<10)
            putchar(x+'0');
        else
        {
            write(x/10);
            putchar(x%10+'0');
        }
    }
}
using namespace IO;
struct edge
{
    int u,v,w;
}a[100005];
struct node
{
    int e;
    int w;
};
int n,m;
int l=0,r=1000000001,mid,cnt,tot;
int d[100005];
int id[100005];
bool used[100005];
queue<int> q;
vector<node> g[100005];
vector<int> dag[100005];
void build(int cnt)
{
    for(int i=1;i<=n;i++)
    	dag[i].clear();
    for(int i=1;i<=n;i++)
    {
    	d[i]=0;
        for(int j=0;j<g[i].size();j++)
        {
            if(g[i][j].w>=cnt)
            {
                dag[g[i][j].e].push_back(i);
                d[i]++;
            }
        }
    }
}
bool topsort()
{
    cnt=0;
    for(int i=1;i<=n;i++)
    {
        used[i]=0;
        if(d[i]==0)
            q.push(i);
    }
    while(!q.empty())
    {
        int t=q.front();
        id[t]=++cnt;
        q.pop();
        used[t]=1;
        for(int i=0;i<dag[t].size();i++)
        {
            int v=dag[t][i];
            d[v]--;
            if(d[v]==0)
                q.push(v);
        }
    }
    for(int i=1;i<=n;i++)
        if(used[i]==0)
            return 0;
    return 1;
}
bool check(int cnt)
{
    build(cnt);
    return topsort();
}
int main()
{
    read(n);read(m);
    for(int i=1,u,v,w;i<=m;i++)
    {
        read(u);read(v);read(w);
        a[i].u=u;a[i].v=v;a[i].w=w;
        g[u].push_back((node){v,w});
    }
    while(l+1<r)
    {
        mid=(l+r)>>1;
        if(check(mid))
            r=mid;
        else
            l=mid;
    }
    while(check(r-1)&&r-1>=1)
        r--;
    check(r);
    write(r-1);putchar(' ');
    for(int i=1;i<=m;i++)
        if(id[a[i].u]<id[a[i].v])
        	tot++;
    write(tot);
	putchar('\n');
	for(int i=1;i<=m;i++)
		if(id[a[i].u]<id[a[i].v])
		{
			write(i);
			putchar(' ');
		}
    return 0;
}
posted @ 2020-08-24 10:00  loney_s  阅读(79)  评论(0)    收藏  举报