解题:POI 2006 PRO-Professor Szu

题面

这个题是比较套路的做法啦,建反图后缩点+拓扑排序嘛,对于所有处在$size>=2$的SCC中的点都是无限解(可以一直绕)

然后注意统计的时候的小细节,因为无限解/大解也要输出,所以我们把这些点统一统计成36501,然后所有的方案都对36501取min就可以很方便的输出了

 1 #include<cstdio>
 2 #include<vector>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int N=1000005,INF=36501;
 7 int P[N],Noww[N],Goal[N];
 8 int p[N],noww[N],goal[N];
 9 int dfn[N],low[N],col[N],deg[N],inf[N];
10 int stk[N],ins[N],que[N],outp[N],dp[N];
11 int n,m,c,f,b,t1,t2,cnt,Cnt,tot,top,ans;
12 void link(int f,int t)
13 {
14     noww[++cnt]=p[f];
15     goal[cnt]=t,p[f]=cnt;
16 }
17 void relink(int f,int t)
18 {
19     Noww[++Cnt]=P[f];
20     Goal[Cnt]=t,P[f]=Cnt;
21 }
22 void Tarjan_SCC(int nde)
23 {
24     dfn[nde]=low[nde]=++tot;
25     stk[++top]=nde,ins[nde]=true;
26     for(int i=p[nde];i;i=noww[i])
27         if(!dfn[goal[i]])
28             Tarjan_SCC(goal[i]),low[nde]=min(low[nde],low[goal[i]]);
29         else if(ins[goal[i]])
30             low[nde]=min(low[nde],low[goal[i]]);
31     if(dfn[nde]==low[nde])
32     {
33         c++; int tmp;
34         do
35         {
36             tmp=stk[top--];
37             ins[tmp]=false;
38             col[tmp]=c;
39         }while(nde!=tmp);
40     }
41 }
42 int main ()
43 {
44     scanf("%d%d",&n,&m),b=-1;
45     for(int i=1;i<=m;i++)
46         scanf("%d%d",&t1,&t2),link(t2,t1);
47     for(int i=1;i<=n+1;i++)
48         if(!dfn[i]) Tarjan_SCC(i);
49     for(int i=1;i<=n+1;i++)
50         for(int j=p[i];j;j=noww[j])
51             if(col[i]!=col[goal[j]])
52             {
53                 relink(col[i],col[goal[j]]);
54                 deg[col[goal[j]]]++;
55             }
56             else inf[col[i]]=true;
57     for(int i=1;i<=c;i++)
58         if(!deg[i]) que[++b]=i;
59     dp[col[n+1]]=1;
60     while(f<=b)
61     {
62         int tn=que[f++];
63         if(inf[tn]&&dp[tn]) dp[tn]=INF;
64         for(int i=P[tn];i;i=Noww[i])
65         {
66             dp[Goal[i]]=min(dp[Goal[i]]+dp[tn],INF);
67             if(!(--deg[Goal[i]])) que[++b]=Goal[i];
68         }
69     }
70     for(int i=1;i<=c;i++) ans=max(ans,dp[i]);
71     for(int i=1;i<=n;i++)
72         if(dp[col[i]]==ans) outp[++outp[0]]=i;
73     ans>36500?printf("zawsze"):printf("%d",ans);
74     puts(""),printf("%d\n",outp[0]);
75     for(int i=1;i<=outp[0];i++)
76         printf("%d ",outp[i]);
77     return 0;
78 }

原文地址:https://www.cnblogs.com/ydnhaha/p/9839528.html

时间: 2024-10-17 08:47:28

解题:POI 2006 PRO-Professor Szu的相关文章

BZOJ 1513 POI 2006 Tet-Tetris 3D 二维线段树

题目大意:三维俄罗斯方块,问最后摞了多高. 思路:二维线段树的裸题.但是要注意二维线段树不支持标记下穿.所以就不下传,每次更新答案的时候先看标记,然后用所有的跟标记比较大小之后返回. 具体看代码吧,不知道怎么说. CODE: #define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define

Java.lang.Object.clone()分析

首先,看一下源码: 1 public class Object { 2 protected native Object clone() throws CloneNotSupportedException; 3 } 由源代码我们会发现: 第一:Object类的clone()方法是一个native方法,native方法的效率一般来说都是远高于Java中的非native方法.这也解释了为什么要用Object中clone()方法而不是先new一个类,然后把原始对象中的信息复制到新对象中,虽然这也实现了c

对象的复制(clone、序列化)

那就先看是clone方法复制对象  摘自 java.lang.Object.clone()分析 首先,看一下源码:public class Object  {    protected native Object clone() throws CloneNotSupportedException;} 由源代码我们会发现: 第一:Object类的clone()方法是一个native方法,native方法的效率一般来说都是远高于Java中的 非native方法.这也解释了为什么要用Object中cl

Java clone方法(下)

1.最终调用的是一个JNI方法,即java本地方法,加快速度 2.使用clone方法,分为浅复制.深复制,这里直接使用网上抄来的案例来说明吧: 说明: 1)为什么我们在派生类中覆盖Object的clone()方法时,一定要调用super.clone()呢?在运行时刻,Object中的clone()识别你要复制的是哪一个对象,然后为此对象分配空间,并进行对象的复制,将原始对象的内容一一复制到新对象的存储空间中. 2)继承自java.lang.Object.clone()方法是浅层复制.一下代码可以

Poi 2014 解题报告( 1 - 4 ,6 )

撸了一下Poi 2014 ,看了一下网上题解不多,所以决定写一下.有的题应该是数据不强水过去了,等北京回来在写一下复杂度比较靠谱的代码 o(╯□╰)o 第一题: 题意是给定一个长度不大于1000000,只包括p和j的串,求一个最长的子串,要求子串任何一个前缀和后缀都满足p的数量不少于j的数量. 首先把p当做1,把j当做0,算出前缀和 sum[] ,原来的问题就转化为求一个最长区间 [l,r] ,使得任意的i∈[l,r],都有 sum[i] - sum[l-1] >= 0 并且 sum[r] -

NOIP 2006 解题报告

第一题: 在Mars星球上,每个Mars人都随身佩带着一串能量项链.在项链上有N颗能量珠.能量珠是一颗有头标记与尾标记的珠子,这些标记对应着某个正整数.并且,对于相邻的两颗珠子,前一颗珠子的尾标记一定等于后一颗珠子的头标记.因为只有这样,通过吸盘(吸盘是Mars人吸收能量的一种器官)的作用,这两颗珠子才能聚合成一颗珠子,同时释放出可以被吸盘吸收的能量.如果前一颗能量珠的头标记为m,尾标记为r,后一颗能量珠的头标记为r,尾标记为n,则聚合后释放的能量为(Mars单位),新产生的珠子的头标记为m,尾

解题:POI 2013 Triumphal arch

题面 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=300005; 6 int n,t1,t2,cnt,l,r,mid,ans; 7 int p[N],noww[2*N],goal[2*N]; 8 int son[N],dp[N]; 9 void link(int f,int t) 10 { 11 noww[++cnt]=

解题:POI 2010 Beads

题面 正反各做一遍哈希来判断,然后在两个哈希值里取一个$max/min$做哈希值,然后每次把子串们的哈希插进$set$里,最后统计集合大小,就可以优秀地在$O(nlog^2$ $n)$中出解了 然后我觉得这样太没有理想了,就写了一个挂链哈希表,结果跑的贼慢... 我挂链时的区分方法是换模数再模出一个新值,然后这样做的时候注意要和哈希表的基数和模数区分开 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm>

解题:POI 2008 Subdivision of Kingdom

题面 还可以这么搜......学到了(PoPoQQQ orz) 我们最朴素的做法是枚举所有状态(当然可以剪,剪完最终实际状态量也是$C_{26}^{13}$的),然后每次$O(n)$扫一遍判断,大概会T炸,考虑优化 我们先预处理每个状态中$1$的数目和连边的状态,然后压缩状态初始让一边集合为空,一边集合为全集,这样每次从已有的点的前面$\frac{n}{2}$个点中枚举一个加入另一边,就可以边搜边更新边数而不用最后$O(n)$检查了.另一个问题是数组可能非常大,这里我们可以把状态拆成前后两半,然