破坏基地

来源:互联网 发布:js position 编辑:程序博客网 时间:2024/04/23 15:37

    这个是在ZJOI2012Day2 T1的启发下出的一道ws题。

       首先我们用dijkstra算法求出这个图的所有点关于节点1的最短路(鉴于不是时间的卡点,所以时间复杂度忽略不计了),我们构建一个关于节点1的最短路可拓扑图。大概就是若一条边(u,v,w)满足d(u)+w=d(v),那么这条边(当然要注意有方向)就在最短路可拓扑图中。

       我们若在这个可拓扑图中删掉一个点P,使得节点1和节点N不连通,那么就说明节点P满足条件。

       这里,我们再构建一棵神奇的树(当然,我们这里所说的所有图和树,他们的节点编号都是一一对应的,也就是说在任意一个图中的节点x对应于另一个图的节点x)

       这棵树满足删掉了某个节点,那么以这个节点的子树的所有节点的关于节点1的最短路都会发生变化。

       现在我们来构建这样一个树。

       首先,节点1是树的根节点。

       然后,节点x的父节点就是在最短路可拓扑图中所有前驱的最近公共祖先。

       这样我们就构建好了这棵树。

       然后,根据我们之前所说过的对于这个构建出来的树的性质,就可以知道,这棵树中节点1和节点N之间(不含两端)的那些节点就是满足条件的节点。

       这里我们可以O(N^2)构建出这棵树,常数较小。

#include <iostream>#include<cstdio>#include<cstdlib>#include<climits>#include<climits>#include<algorithm>#include<cstring>using namespace std;int q[10001],b[400001],next[400001],list[10001],d[10001],cost[400001];bool kill[10001],f[10001];int pre[10001]={0},p[10001]={0},ans[10001];int n,m,ansi,tot=0,Min;void init(){    int u,v,w;    scanf("%d %d",&n,&m);    for(int i=1;i<=m;i++)    {        scanf("%d %d %d",&u,&v,&w);        tot++;        b[tot]=v;        cost[tot]=w;        next[tot]=list[u];        list[u]=tot;        tot++;        b[tot]=u;        cost[tot]=w;        next[tot]=list[v];        list[v]=tot;    }}void spfa(){    int head,tail,nw,k;    head=1;tail=2;    q[head]=1;    memset(f,0,sizeof(f));    memset(d,0x3f,sizeof(d));    f[1]=true;d[1]=0;    while(head!=tail)    {        nw=q[head];        head++;        f[nw]=false;        if(head>10000) head=1;        k=list[nw];        while(k!=0)        {            if(kill[b[k]]==false)            {                if(d[b[k]]>d[nw]+cost[k])                {                    d[b[k]]=d[nw]+cost[k];                    pre[b[k]]=nw;                     if(f[b[k]]==false)                     {                        f[b[k]]=true;                        if(d[q[head]]>d[b[k]])                        {                            head--;                            if(head==0)head=10000;                            q[head]=b[k];                        }                        else                        {                            q[tail]=b[k];                            tail++;                            if(tail>10000)tail=1;                        }                     }                }            }            k=next[k];        }    }}int main(){    freopen("destroy.in","r",stdin);    freopen("destroy.out","w",stdout);    int s,k;    init();    memset(kill,false,sizeof(kill));    spfa();    s=pre[n];k=0;    while(pre[s]!=0)    {        k++;        p[k]=s;        s=pre[s];    }    Min=d[n];ansi=0;    for(int i=1;i<=k;i++)    {        kill[p[i]]=true;        spfa();        if(Min!=d[n])        {            ansi++;            ans[ansi]=p[i];        }        kill[p[i]]=false;    }    sort(&ans[1],&ans[ansi]+1);    printf("%d\n",ansi);    for(int i=1;i<=ansi;i++)    printf("%d\n",ans[i]);    return 0;    fclose(stdin);    fclose(stdout);}

0 0
原创粉丝点击