hdu 4871 Shortest-path tree 树分治

来源:互联网 发布:汉字笔顺演示软件下载 编辑:程序博客网 时间:2024/06/09 17:19

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4871

题目大意:给你一个图G,让你按照某种方式做一棵生成树,然后,在树上找含有K个节点的路径,使得路径最长,并输出最长路径的条数!

解题思路:还是树分治,而且是一个比较裸的树分治。对于当前的树,找到重心,然后处理与重心相连的所有节点,维护f[] 数组,f[i] 表示已经处理的子树中有i个节点的路径的最长的长度,r[] 数组表示已经处理的子树中有i个节点的最长路径的条数,然后暴力处理每一个子树!然后递归处理下去

//#pragma comment(linker,"/STACK:102400000,102400000")#include<stdio.h>#include<iostream>#include<string.h>#include<math.h>#include<algorithm>#include<vector>#include<map>#include<set>#include<queue>#include<string>#define ll long long#define db double#define PB push_backusing namespace std;const int N = 30005;const int M = 60006;const int INF = 1000000000;vector<int> v[N];int dist[N],bf[N],val[N];bool mk[N];void spfa(int n){    for(int i=1;i<=n;i++) dist[i]=INF;    memset(mk,false,sizeof(mk));    memset(bf,-1,sizeof(bf));    mk[1]=true;    dist[1]=0;    queue<int> q;    q.push(1);    while(!q.empty())    {        int t=q.front();        q.pop();        mk[t]=false;        for(int i=0;i<v[t].size();i+=2)        {            int ed=v[t][i];            if(dist[ed]>dist[t]+v[t][i+1])            {                dist[ed]=dist[t]+v[t][i+1];                val[ed]=v[t][i+1];                bf[ed]=t;                if(!mk[ed]) mk[ed]=true,q.push(ed);            }else if(dist[ed]==dist[t]+v[t][i+1])            {                val[ed]=v[t][i+1];                if(bf[ed]==-1) bf[ed]=t;                else bf[ed]=min(bf[ed],t);            }        }    }}int head[N],to[M],next[M],cost[M],nedge;void init(){    memset(head,-1,sizeof(head));    nedge=0;}void add(int a,int b,int c){    to[nedge]=b,cost[nedge]=c,next[nedge]=head[a],head[a]=nedge++;}int max_node[N],tol[N],root,min_val;//INFbool vis[N];void get_root(int k,int &n){    tol[k]=1,max_node[k]=0;    vis[k]=true;    for(int i=head[k];i>=0;i=next[i])    {        if(!vis[to[i]])        {            get_root(to[i],n);            max_node[k]=max(tol[to[i]],max_node[k]);            tol[k]+=tol[to[i]];        }    }    max_node[k]=max(max_node[k],n-tol[k]);    if(max_node[k]<min_val)    {        min_val=max_node[k];        root=k;    }    vis[k]=false;}int f[N],r[N];void get_f(int k,int sum){    f[k]=sum;    vis[k]=true;    for(int i=head[k];i>=0;i=next[i])    {        if(!vis[to[i]])        {            get_f(to[i],sum+1);            f[k]=max(f[k],f[to[i]]);        }    }    vis[k]=false;}bool cmp(int a,int b){    return f[to[a]]<f[to[b]];}int cnt,ch[N],g[N];void get_g(int k,int sum,int ct){    g[cnt]=sum,ch[cnt++]=ct;    vis[k]=true;    for(int i=head[k];i>=0;i=next[i])    {        if(!vis[to[i]])        {            get_g(to[i],sum+1,ct+cost[i]);        }    }    vis[k]=false;}int num[N];int dep,max_k,ans;ll number;void work(int k,int n){    min_val=INF;    get_root(k,n);    int rt=root;    vis[rt]=true;    for(int i=head[rt];i>=0;i=next[i])    {        if(!vis[to[i]])        {            if(tol[to[i]]>tol[rt]) work(to[i],n-tol[rt]);            else work(to[i],tol[rt]);        }    }    int l=0;    for(int i=head[rt];i>=0;i=next[i])    {        if(!vis[to[i]])        {            get_f(to[i],1);            num[l++]=i;        }    }    if(l==0) {vis[rt]=false;return;}    sort(num,num+l,cmp);    dep=f[to[num[l-1]]];    for(int i=1;i<=dep;i++) f[i]=-1;    r[0]=1;    for(int i=0;i<l;i++)    {        int ed=to[num[i]];        if(!vis[ed])        {            cnt=0;            get_g(ed,1,cost[num[i]]);            for(int j=0;j<cnt;j++)            {                if(g[j]+1>max_k) continue;                int t=max_k-g[j]-1;                if(t<=dep&&f[t]!=-1)                {                    if(f[t]+ch[j]>ans)                    {                        ans=f[t]+ch[j];                        number=r[t];                    }else if(f[t]+ch[j]==ans)                    {                        number+=r[t];                    }                }            }            for(int j=0;j<cnt;j++)            {                if(g[j]>max_k) continue;                if(f[g[j]]==-1) f[g[j]]=ch[j],r[g[j]]=1;                else                {                    if(ch[j]>f[g[j]]) f[g[j]]=ch[j],r[g[j]]=1;                    else if(ch[j]==f[g[j]]) r[g[j]]++;                }            }        }    }    vis[rt]=false;}int main(){#ifdef PKWV    freopen("1011.in","r",stdin);    freopen("out.out","w",stdout);#endif // PKWV    int T;    scanf("%d",&T);    while(T--)    {        int n,m;        scanf("%d%d%d",&n,&m,&max_k);        for(int i=1;i<=n;i++) v[i].clear();        for(int i=0;i<m;i++)        {            int a,b,c;            scanf("%d%d%d",&a,&b,&c);            v[a].PB(b),v[a].PB(c);            v[b].PB(a),v[b].PB(c);        }        spfa(n);        init();        for(int i=2;i<=n;i++)        {            add(i,bf[i],val[i]);            add(bf[i],i,val[i]);        }        ans=0,number=0LL;        work(1,n);        printf("%d %I64d\n",ans,number);    }    return 0;}


0 0
原创粉丝点击