首页 > 其他分享 >今晚题解

今晚题解

时间:2022-11-17 16:48:29浏览次数:52  
标签:今晚 硬币 int 题解 拓扑 tot 朝上 翻转

题意概述

给定一张 \(n\) 个点 \(m\) 条边的有向图 \(G\) 。

有 \(n\) 个硬币。初始时有的正面朝上,有的反面朝上。每次你可以手动翻转一枚。

如果在 \(G\) 中有边 \(a\rightarrow b\) ,那么当第 \(a\) 枚硬币(被手动或自动)翻转后,第 \(b\) 枚也会被自动翻转。注意:它可以传递下去。

但如果你手动翻转某一枚后会触发无限次操作,那波特就直接炸了,你不能使其触发这种情况。

给定初始每个硬币的状态,求至少操作多少次后能使所有硬币都正面朝上。

无解输出 -1 。

思路概述

这道题其实是一个拓扑排序的思维题,先反向拓扑排序判断是不是无解,反向拓扑之后,如果剩下的点有反着的硬币,则说明无解(我考场上就想到这里了),因为如果有这样的反着的硬币,那一定不能成。然后正着拓扑,同时记下到这个点的翻转次数,如果当前点翻转次数是奇数且是正面朝上或者翻转次数是偶数且是负面朝上,那就该翻转这个点,一直这样跑完就行了。

code

#include<bits/stdc++.h>
using namespace std;

const int N=5e5+10;
int n,m,a[N];
int to[N],nxt[N],h[N],tot;
int deg[N],Deg[N],v[N],cnt[N];
int res;
vector<int> ver[N];
int X[N],Y[N];

void add(int x,int y)
{
    to[++tot]=y;
    nxt[tot]=h[x];
    h[x]=tot;
    deg[y]++;
}

void topsort_()
{
    queue<int> q;
    for(int i=1;i<=n;i++)if(!deg[i])q.push(i),v[i]=true;
    while(q.size())
    {
        int x=q.front();
        q.pop();
        for(int i=h[x];i;i=nxt[i])
        {
            int y=to[i];
            if(--deg[y]==0)q.push(y),v[y]=true;
        }
    }
}

bool judge()
{
    for(int i=1;i<=n;i++)
    {
        if(!v[i]&&!a[i])return false;
    }
    return true;
}

bool need(int x)
{
    if(!a[x]&&!(cnt[x]%2))return true;
    if(a[x]&&(cnt[x]%2))return true;
    return false;
}

void topsort()
{
    queue<int> q;
    for(int i=1;i<=n;i++)
    {
        if(!Deg[i])
        {
            q.push(i);
        }
    }
    while(q.size())
    {
        int x=q.front();
        q.pop();
		if(need(x))cnt[x]++,res++;
        for(int y:ver[x])
        {
            cnt[y]+=cnt[x];
            if(--Deg[y]==0) q.push(y);
        }
    }
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        add(y,x);
		X[i]=x;
		Y[i]=y;
    }
    topsort_();
    if(!judge())
    {
        cout<<-1;
        return 0;
    }
	for(int i=1;i<=m;i++)
	{
		int x=X[i];
		int y=Y[i];
		if(!v[x]||!v[y])continue;
		ver[x].push_back(y);
		Deg[y]++;
	}
    topsort();
    cout<<res;
    return 0;
}

标签:今晚,硬币,int,题解,拓扑,tot,朝上,翻转
From: https://www.cnblogs.com/Eternal-QX/p/16899916.html

相关文章

  • Aizu 2378 SolveMe 题解 (置换,计数)
    题目链接题意简述有一个n个点的有向图,每个点有两条出边,称为A边和B边。称一种构图是好的,当且仅当对于所有i,从第i个点出发,先连走x次A边,走1次B边,再连走y次A边,走1次B边,再走z......
  • CF1181C Flag 题解
    题意:问在一个\(n\timesm\)的平面里有多少旗帜,旗帜的定义是三条宽度相等的带子,相邻的带子颜色不能相同(第一和第三条的颜色可以相同)。考虑以左上角统计旗帜,预处理每个点......
  • 小程序获取不到用户头像和昵称返回微信用户问题解决,即小程序授权获取用户头像规则调整
    最近好多同学在学习石头哥小程序课程的时候,遇到了下面这样的问题,在小程序授权获取用户头像和昵称时,获取到的是下面这样的。到底是什么原因导致的呢,去小程序官方文档一看,又是......
  • Codeforces Gym 100958 E Cellular Automaton (Makoto rng_58 Soejima contest) 题解
    题目链接其实"序列中1的数量有限"是一个非常重要的条件。这意味着我们可以找到序列中的第一个1和最后一个1。考虑这样一件事情:初始时我们把一个长度为\(2^{2w+1}\)的"滑......
  • CF707E Garlands 题解
    简要题意:在一个\(n\timesm\)的矩阵(\(n,m\le2000\))中,每个点都有个灯,刚开始所有灯都是亮的,每个灯都有一个颜色(\(k\le2000\))和一个权值,保证所有颜色相同的点是联通块。现......
  • UVA1331 题解
    前言题目传送门!更好的阅读体验?计算几何、区间DP。思路......
  • T292306 01最短路 题解
    又是一个找不到题目所以自己写的题。。。40迪杰斯特拉,但是搞不懂为什么是wa而不是re的#include<bits/stdc++.h>#definefor1(i,a,b)for(inti=a;i<=b;i++)#definell......
  • 紫罗兰题解
    题意概述给定一张\(n\)个顶点\(m\)条边的无向图,顶点的编号在\(1\simn\)内,第\(i\)条无向边连接着顶点\(x_i\)与\(y_i\)。我们称顶点\(v_0,v_2,\cdots,v_{k......
  • DTOJ 2022-11-15 测试 题解
    测试成果100+100+50+10=260还行吧(虽然T2做法很迷惑)A惊鸿(grace)DTOJP6367题面大意给定一个\(n\)行\(m\)列的仅包含小写字母的矩阵\(A\)。求从\((1,1)\)......
  • 长春花题解
    题意概述给定一个素数\(p\),对每个\(0\lex<p\),设\(f(x)\)表示一个最小的非负整数\(a\),使得存在一个非负整数\(b\),满足\((a^2+b^2)\bmodp=x\)。现在,你想要......