51Nod 1815 調查任務

發現紹一的人很喜歡作51nod,不得不說這仍是一個很全能的良心OJgit

可是作的這道題就一點都不良心了,簡直是毒瘤,調了一早上數組

首先咱們考慮讓一條路徑的\(a_x\ mod\ a_y\)的值最大,咱們簡單分析一波能夠得出一個結論:spa

\(a_x\)爲這條路徑上的嚴格次大數,且\(a_y\)爲最大數時,答案最大,且答案爲\(a_x\)很顯然吧,我來稍微證實一下:code

設最大值爲\(a_u\ mod\ a_v\),則排序

  • \(a_v=a_y\)時,此時\(a_u\ mod\ a_v=a_u\),所以取出\(a_x\)更優
  • \(a_v\ne a_y\)時,此時\(a_u\ mod\ a_v<a_v\),此時即便令\(a_v=max(a_i)=a_x\),亦有\(a_u\ mod\ a_v<a_x\)

而後咱們有在題目中發現一條十分重要的信息:string

一個點能夠被通過屢次!it

所以一個聯通塊內的點均可以互相到達,所以咱們進行Tarjan縮點,而後考慮拓撲排序更新出最大值最小值io

可是注意一點,一個點只能從一個點轉移過來,剛開始就是沒有考慮到這一點而後WA到死class

具體的操做比較麻煩,仍是看一下CODE吧,解釋一下里面關鍵的幾個數組:im

  • 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;
}
相關文章
相關標籤/搜索