• 51Nod 1815 调查任务


    发现绍一的人很喜欢做51nod,不得不说这还是一个很全能的良心OJ

    但是做的这道题就一点都不良心了,简直是毒瘤,调了一早上

    首先我们考虑让一条路径的(a_x mod a_y)的值最大,我们简单分析一波可以得出一个结论:

    (a_x)为这条路径上的严格次大数,且(a_y)为最大数时,答案最大,且答案为(a_x)很显然吧,我来稍微证明一下:

    设最大值为(a_u mod a_v),则

    • (a_v=a_y)时,此时(a_u mod a_v=a_u),因此取出(a_x)更优
    • (a_v e a_y)时,此时(a_u mod a_v<a_v),此时即使令(a_v=max(a_i)=a_x),亦有(a_u mod a_v<a_x)

    然后我们有在题目中发现一条十分重要的信息:

    一个点可以被经过多次!

    因此一个联通块内的点都可以互相到达,因此我们进行Tarjan缩点,然后考虑拓扑排序更新出最大值最小值

    但是注意一点,一个点只能从一个点转移过来,刚开始就是没有考虑到这一点然后WA到死

    具体的操作比较麻烦,还是看一下CODE吧,解释一下里面关键的几个数组:

    • max1[]:当前联通块内的最小值
    • max2[]:当前联通块内的严格次小值
    • max3[]:当前路径上的最小值
    • max4[]:当前路径上严格次小值

    然后就是细节慢慢的转移了,尤其是注意我多次标注的严格

    最后莫名在51nod上拿了Rank1,并且甩了Rank2的yekehe一截

    CODE

    #pragma G++ optimize (2)
    #pragma comment(linker, "/STACK:10240000,10240000") 
    #include<cstdio>
    #include<cctype>
    #include<cstring>
    using namespace std;
    const int N=4e5+5,M=2e6+5;
    struct edge
    {
    	int to,next;
    }e[M],ne[M];
    int head[N],nhead[N],n,m,q,a[N],max1[N],max2[N],max3[N],max4[N],low[N],dfn[N],col[N],tot,scc,x,y,s,que[N],cnt,stack[N],top,ru[N];
    bool vis[N];
    inline char tc(void)
    {
    	static char fl[100000],*A=fl,*B=fl;
    	return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
    }
    inline void read(int &x)
    {
    	x=0; char ch; while (!isdigit(ch=tc()));
    	while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc()));
    }
    inline void write(int x)
    {
    	if (x>9) write(x/10);
    	putchar(x%10+'0');
    }
    inline void add(int x,int y)
    {
    	e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt;
    }
    inline void nadd(int x,int y)
    {
    	ne[++cnt].to=y; ne[cnt].next=nhead[x]; nhead[x]=cnt;
    }
    inline int min(int a,int b)
    {
    	return a<b?a:b;
    }
    inline int max(int a,int b)
    {
    	return a>b?a:b;
    }
    inline void Tarjan(int now)
    {
    	dfn[now]=low[now]=++tot; stack[++top]=now; vis[now]=1;
    	for (register int i=head[now];i!=-1;i=e[i].next)
    	if (!dfn[e[i].to]) Tarjan(e[i].to),low[now]=min(low[now],low[e[i].to]);
    	else if (vis[e[i].to]) low[now]=min(low[now],dfn[e[i].to]);
    	if (low[now]==dfn[now])
    	{
    		col[now]=++scc; vis[now]=0; max1[scc]=a[now];
    		while (stack[top]!=now)
    		{
    			col[stack[top]]=scc; vis[stack[top]]=0;
    			if (a[stack[top]]>max1[scc]) max2[scc]=max1[scc],max1[scc]=a[stack[top]];
    			else if (a[stack[top]]>max2[scc]&&a[stack[top]]!=max1[scc]) max2[scc]=a[stack[top]]; --top;
    		} --top;
    	}
    }
    inline void top_sort(int s)
    {
    	int H=0,T=1; que[1]=s; vis[s]=1;
    	while (H<T)
    	{
    		int now=que[++H];
    		for (register int i=nhead[now];i!=-1;i=ne[i].next)
    		{
    			++ru[ne[i].to]; if (vis[ne[i].to]) continue;
    			vis[ne[i].to]=1; que[++T]=ne[i].to;
    		}
    	}
    	H=0; T=1; que[1]=s;
    	while (H<T)
    	{
    		int now=que[++H];
    		for (register int i=nhead[now];i!=-1;i=ne[i].next)
    		{
    			max2[ne[i].to]=max(max2[ne[i].to],max2[now]);
                if (max1[ne[i].to]!=max3[now]) max2[ne[i].to]=max(max2[ne[i].to],min(max1[ne[i].to],max3[now]));
                else max2[ne[i].to]=max(max2[ne[i].to],max4[now]);
                if (max3[now]>max3[ne[i].to]) max4[ne[i].to]=max3[ne[i].to],max3[ne[i].to]=max3[now];
                else if (max3[ne[i].to]>max3[now]&&max3[now]>max4[ne[i].to]) max4[ne[i].to]=max3[now];
                if (max4[now]>max3[ne[i].to]) max4[ne[i].to]=max3[ne[i].to],max3[ne[i].to]=max4[ne[i].to];
                else if (max3[ne[i].to]>max4[now]&&max4[now]>max4[ne[i].to]) max4[ne[i].to]=max4[now];
    			if (!(--ru[ne[i].to])) que[++T]=ne[i].to;
    		}
    	}
    }
    int main()
    {
    	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    	register int i,j; read(n); read(m); read(q); read(s);
    	memset(head,-1,sizeof(head)); memset(e,-1,sizeof(e));
    	memset(nhead,-1,sizeof(nhead)); memset(ne,-1,sizeof(ne));
    	for (i=1;i<=n;++i) 
    	read(a[i]);
    	for (i=1;i<=m;++i)
    	read(x),read(y),add(x,y);
    	for (i=1;i<=n;++i)
    	if (!dfn[i]) Tarjan(i);
    	for (cnt=0,i=1;i<=n;++i)
    	for (j=head[i];j!=-1;j=e[j].next)
    	if (col[i]!=col[e[j].to]) nadd(col[i],col[e[j].to]);
    	memcpy(max3,max1,sizeof(max3)); memcpy(max4,max2,sizeof(max4)); top_sort(col[s]);
    	while (q--)
    	{
    		read(x); if (!vis[col[x]]) printf("-1 ");
    		else write(max2[col[x]]),putchar(' ');
    	}
    	return 0;
    }
    
  • 相关阅读:
    从零实现一个功能完善的迷你区块链
    Merkle Tree理解起来并不难
    微信、支付宝个人收款的一种实现思路
    PostgreSQL的登录、创建用户、数据库并赋权
    java list 按照多字段排序
    2019年最新全国省市区街道共46462条数据(统计局MySQL数据库)
    一份非常值得一看的Java面试题
    spring scope prototype与singleton
    http请求与响应,TCP三次握手&四次分手
    HTTP协议三次握手过程
  • 原文地址:https://www.cnblogs.com/cjjsb/p/9339073.html
Copyright © 2020-2023  润新知