cf(tarjan运用+链表)

来源:互联网 发布:merline mac 破解版 编辑:程序博客网 时间:2024/06/03 17:08
/*给你有向图,有些边是可以直接走的,有些边是修之后才可以走,现在要想从1能到达所有的点,问你至少要修多少条路。解:现把 可以直接 走的边加进来,缩点,因为(1<n,m<1e6)。      然后从1点bfs,每个点初始都为0,可以直接的标记为-1,要修的边标记为边的编号,当再有不修路就能到达的话又把它标记为-1,。      所以,如果路全部修之后好不能到达,则有些点还为0。      点的标记>0,则说明修路之后才能到达。       要记录边的编号,应该用数组模拟邻接链表。*/#include<cstdio>#include<cstring>#include<iostream>#define N 100030using namespace std;int head[N];int n,m,x,y;int dfn[N],low[N],instack[N],num[N],edge[N],f[N],o[N],top,D,now,ans;bool inst[N];struct Node{    int u,v,f;    int next;}ed[N];void tarjan(int i){    dfn[i]=low[i]=++D;    inst[i]=1,instack[++top]=i;    for (int p=head[i]; p; p=ed[p].next)    {        int j=ed[p].v;        if(ed[p].f)continue;        if (!dfn[j]) tarjan(j),low[i]=min(low[i],low[j]);        else if (inst[j]) low[i]=min(low[i],dfn[j]);    }    if (low[i]==dfn[i])    {        now++;        int k;        do k=instack[top--],inst[k]=0,num[k]=now;        while (k!=i);    }}void bfs(int x){    int h=0,t=1;    f[1]=x;    edge[x]=-1;    while (h<t)    {        int i=f[++h];        for (int p=head[i]; p; p=ed[p].next)        {            //int j=vv[p];            int j=ed[p].v;            if (!edge[j]) edge[j]=ed[p].f ?p:-1,f[++t]=j;            else if (edge[j]>0 && !ed[p].f) edge[j]=-1;        }    }}void init(){    memset(head,0,sizeof(head));    memset(dfn,0,sizeof(dfn));    memset(low,0,sizeof(low));    memset(edge,0,sizeof(edge));    top=0;    D=0;    now=0;}void add(int u,int v,int f,int e){    ed[e].u=u;    ed[e].v=v;    ed[e].f=f;    ed[e].next=head[u];    head[u]=e;}int main(){    freopen("input.txt","r",stdin);    freopen("output.txt","w",stdout);    while(scanf("%d%d",&n,&m)!=EOF)    {        init();        int u,v,f;        for (int i=1; i<=m; i++)        {            cin>>u>>v>>f;            add(u,v,f,i);        }        for (int i=1; i<=n; i++)            if (!dfn[i])                tarjan(i);        memset(head,0,sizeof(head));        for (int i=1; i<=m; i++)        {            //int x=num[uu[i]],y=num[vv[i]];            //vv[i]=y;           // if (x!=y) next[i]=head[x],head[x]=i;           int x=num[ed[i].u];           int y=num[ed[i].v];           int f=ed[i].f;           if(x!=y)           {               add(x,y,f,i);           }        }        bfs(num[1]);        ans=0;        for (int i=1; i<=now; i++)            if (edge[i]>0)                o[++ans]=edge[i];        for (int i=1; i<=now; i++)            if (!edge[i])                ans=-1;        printf("%d\n",ans);        for (int i=1; i<=ans; i++)            printf("%d%s",o[i],i<ans?" ":"\n");    }    return 0;}