• 【JZOJ3800】败屩妖


    题目

    题目链接:https://jzoj.net/senior/#main/show/3800

    思路

    裸题。
    二分\(C\),然后只走边权大于\(mid\)的边,把每一个连通块染色。然后再枚举每一个询问,如果均不能到达则\(mid\)是一个合法方案,反之不行。
    时间复杂度\(O((n+m)\log maxdis)\)

    代码

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int N=100010,M=600010;
    int n,m,Q,maxn,tot,head[N],pos[N];
    
    struct edge
    {
    	int next,to,dis;
    }e[M];
    
    struct Ask
    {
    	int x,y;
    }ask[N];
    
    void add(int from,int to,int dis)
    {
    	e[++tot].to=to;
    	e[tot].dis=dis;
    	e[tot].next=head[from];
    	head[from]=tot;
    }
    
    void dfs(int x,int id,int mid)
    {
    	pos[x]=id;
    	for (int i=head[x];~i;i=e[i].next)
    		if (e[i].dis>mid && !pos[e[i].to])
    			dfs(e[i].to,id,mid);
    }
    
    bool check(int mid)
    {
    	memset(pos,0,sizeof(pos)); tot=0;
    	for (int i=1;i<=n;i++)
    		if (!pos[i]) dfs(i,++tot,mid);
    	for (int i=1;i<=Q;i++)
    		if (pos[ask[i].x]==pos[ask[i].y]) return 0;
    	return 1;
    }
    
    int main()
    {
    	memset(head,-1,sizeof(head));
    	scanf("%d%d%d",&n,&m,&Q);
    	for (int i=1,x,y,z;i<=m;i++)
    	{
    		scanf("%d%d%d",&x,&y,&z);
    		add(x,y,z); add(y,x,z);
    		maxn=max(maxn,z);
    	}
    	for (int i=1;i<=Q;i++)
    	{
    		scanf("%d%d",&ask[i].x,&ask[i].y);
    		if (ask[i].x==ask[i].y) return !printf("-1");
    	}
    	int l=0,r=maxn,mid;
    	while (l<=r)
    	{
    		mid=(l+r)>>1;
    		if (check(mid)) r=mid-1;
    			else l=mid+1;
    	}
    	printf("%d",r+1);
    	return 0;
    }
    
  • 相关阅读:
    547. Friend Circles
    399. Evaluate Division
    684. Redundant Connection
    327. Count of Range Sum
    LeetCode 130 被围绕的区域
    LeetCode 696 计数二进制子串
    LeetCode 116 填充每个节点的下一个右侧节点
    LeetCode 101 对称二叉树
    LeetCode 111 二叉树最小深度
    LeetCode 59 螺旋矩阵II
  • 原文地址:https://www.cnblogs.com/stoorz/p/12111431.html
Copyright © 2020-2023  润新知