Codeforces Round #436 (Div. 2)

来源:互联网 发布:笔画笔顺查询软件 编辑:程序博客网 时间:2024/05/17 07:18

这套题…
前两题出的太慢了,A题题目看的太慢,然后单纯模拟,wa了两发,然后重写了一下过了。
BC没有什么问题。
D题,emmm,是先减再换,不小心先换再减了,又贡献了几发==
E题,有限制条件的01背包,在这片博客的最后有分析
F题。参考了代码

开始感觉就是个离线操作,将所有询问都存下来,将相同起点的一起询问(询问就是dfs),然后时间复杂度为n*m。

dfs开始想的比较单纯,从起点开始走字典序最小的那条路,在遍历的点中,如果是要查询的终点的话,就把答案记下来。如果遇到环的话全部跳出,没有遍历到的询问就都为-1.

然后WA了,因为首先,如果有环的话,不一定要直接跳出,有些点还要遍历,比如这个图

1 2
2 3
3 4
4 5
2 5
如果查1 5 2的话,结果就是-1。但是1到5并不经过那个环。所以说,这个就是要判断1个点到另一个的路径上有没有环
如果有环的话,回到这个环的起点,继续dfs,那么可以用tarjan

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#include <vector>#include <set>using namespace std;#define ll long long#define mem(a,b) memset(a,b,sizeof(a))const int inf =1e6;const int maxn = 3010;int st[maxn],dfn[maxn],res[400010],low[maxn],vis_st[maxn];struct node{    int id,from,to,k;    node(){}    node(int a,int d,int b,int c){         id=a,from=d,to=b,k=c;    }};node qs[400010];vector<int> v[maxn];vector<node> Q[maxn];bool cmp(node a1,node a2){    if(a1.from!=a2.from)    return a1.from<a2.from;    else return a1.to<a2.to;}int top=0,tot=0;void Tarjan(int u,int ok){    st[++top]=u;    dfn[u]=++tot;    low[u]=inf;//这个开始设为比较大的数,之后如果low比dfn小的话,证明之间有环    vis_st[u]=1;    if(ok)        for(int i=0;i<Q[u].size();i++)            if(Q[u][i].k<=top) res[Q[u][i].id]=st[Q[u][i].k];    for(int i=0;i<v[u].size();i++)    {        int t=v[u][i];        if(!dfn[t])        {            Tarjan(t,ok&&dfn[u]<low[u]);            low[u]=min(low[u],low[t]);        }        else if(vis_st[t]) low[u]=min(low[u],dfn[t]);    }    vis_st[u]=0;    top--;}int main(){    int n,m,q;    scanf("%d %d %d",&n,&m,&q);    memset(res,-1,sizeof(res));    for(int i=0;i<m;i++)    {        int a,b;        scanf("%d %d",&a,&b);        v[a].push_back(b);    }    for(int i=1;i<=n;i++)       sort(v[i].begin(),v[i].end());    for(int i=1;i<=q;i++)    {        int a,b,k;        scanf("%d %d %d",&a,&b,&k);        qs[i]=node(i,a,b,k);    }    sort(qs+1,qs+q+1,cmp);    for(int i=1;i<=q;i++)    {        Q[qs[i].to].push_back(qs[i]);        if(qs[i].from!=qs[i+1].from)        {            mem(st,0);mem(dfn,0);mem(vis_st,0);mem(low,0);            tot=0,top=0;            Tarjan(qs[i].from,1);            for(int j=1;j<=n;j++)                Q[j].clear();        }    }    for(int i=1;i<=q;i++)        printf("%d\n",res[i]);    return 0;}
原创粉丝点击