• [CSP-S模拟测试]:循环依赖(拓扑)


    题目传送门(内部题148)


    输入格式

      每个测试点第一行为一个正整数$T$,表示该测试点内的数据组数。
      接下来$T$组数据,每组数据第一行一个正整数$n$,表示有引用单元格进行计算的单元格数,接下来$n$行,每行第一个字符串为该单元格编号,接下来若干个字符串表示该单元格引用的单元格编号。


    输出格式

      对于每一组测试数据,若有循环依赖,则输出$Yes$,否则输出$No$。


    样例

    样例输入:

    3
    1
    AA13 AA13
    3
    B1 A1 A2
    C1 B1 A1
    A2 C1 A1
    4
    B1 A1
    C1 B1 A1
    D1 C1 B1 A1
    E1 D1 C1 B1 A1

    样例输出:

    Yes
    Yes
    No


    数据范围与提示

    样例解释:

      第一组数据中,$AA13$单元格引用自身,构成了自循环依赖。
      第二组数据描述了题面中的例子。
      第三组数据中,$B1$引用了$A1$,$C1$引用了$B1$和$A1$,以此类推到$E1$,每一个单元格只会引用在该单元格之前列的单元格的值,因此不会构成循环依赖。

    数据范围:

      对于$20\%$的数据,有$1leqslant nleqslant 10$。
      对于$50\%$的数据,有$1leqslant nleqslant 100$。
      对于另外$30\%$的数据,每个单元格至多引用一个单元格。
      对于$100\%$的数据,有$1leqslant nleqslant 30,000$,单元格编号为长度不超过$10$的字符串,每个单元格都引用不超过$10$个单元格(计重数,下同),每组数据中单元格编号的数量$leqslant 90,000$,每个测试点中单元格编号的总数量不超过$450,000$,在任意一组数据中,每行第一个单元格编号不重复,但每个单元格所引用的单元格编号可能重复。


    题解

    玄学读入,离散化,建图,拓扑,一遍过样例!

    一脸懵逼……

     

    发现旁边同学也都是这样额。

    其实

     

    $ ightarrow$$=$

    出题人居然用$Windows$造数据!!!

    换行附在$NOILinux$下是 而在$Windows$下是 。

    剩下的就很裸了,不过如果你想用$tarjan$判环我也不拦你。

    时间复杂度:$Theta(m)$($m$表示依赖关系数)。

    期望得分:$100$分。

    实际得分:$100$分。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    unordered_map<unsigned long long,int>mp;
    struct rec{int nxt,to;}e[200001];
    int head[100001],cnt;
    int n;
    char ch[20];
    int top,tot;
    int du[100001];
    queue<int> q;
    unsigned long long hsh[500001];
    unsigned long long hd[100001];
    vector<unsigned long long>son[100001];
    void pre_work()
    {
    	mp.clear();cnt=top=tot=0;
    	memset(head,0,sizeof(head));
    	memset(son,0,sizeof(son));
    	memset(du,0,sizeof(du));
    }
    unsigned long long get()
    {
    	int len=strlen(ch+1);unsigned long long res=0;
    	for(int i=1;i<=len;i++)res=res*131+ch[i]-'0';
    	return res;
    }
    void add(int x,int y)
    {
    	e[++cnt].nxt=head[x];
    	e[cnt].to=y;
    	head[x]=cnt;
    }
    bool topsort()
    {
    	int res=0;
    	for(int i=1;i<=tot;i++)if(!du[i]){q.push(i);res++;}
    	while(q.size())
    	{
    		int x=q.front();q.pop();
    		for(int i=head[x];i;i=e[i].nxt)
    		{
    			du[e[i].to]--;
    			if(!du[e[i].to]){res++;q.push(e[i].to);}
    		}
    	}
    	return res==tot;
    }
    int main()
    {
    	int T;
    	scanf("%d",&T);
    	while(T--)
    	{
    		scanf("%d",&n);
    		pre_work();
    		for(int i=1;i<=n;i++)
    		{
    			scanf("%s",ch+1);
    			hd[i]=get();
    			hsh[++top]=hd[i];
    			char c=getchar();
    			while(c!='
    ')
    			{
    				scanf("%s",ch+1);
    				hsh[++top]=get();
    				son[i].push_back(hsh[top]);
    				c=getchar();
    			}
    		}
    		sort(hsh+1,hsh+top+1);
    		for(int i=1;i<=top;i++)if(hsh[i]!=hsh[i-1])mp[hsh[i]]=++tot;
    		for(int i=1;i<=n;i++)
    		{
    			hd[i]=mp[hd[i]];
    			for(int j=0;j<son[i].size();j++)
    				son[i][j]=mp[son[i][j]];
    		}
    		for(int i=1;i<=n;i++)
    			for(int j=0;j<son[i].size();j++)
    			{add(son[i][j],hd[i]);du[hd[i]]++;}
    		puts(topsort()?"No":"Yes");
    	}
    	return 0;
    }
    

    rp++

  • 相关阅读:
    Java实时读取日志文件
    Trie树的应用:查询IP地址的ISP
    vue.extend,mixins和vue.component的区别
    前端性能优化10个方面
    vue组件和插件是实现
    vue指令用法
    promise retry实现
    linux管道与重定向
    linux文件颜色与类型
    linux文件权限说明
  • 原文地址:https://www.cnblogs.com/wzc521/p/11845556.html
Copyright © 2020-2023  润新知