bzoj 4016: [FJOI2014]最短路径树问题

来源:互联网 发布:js获取cookie过期时间 编辑:程序博客网 时间:2024/05/18 03:34

4016: [FJOI2014]最短路径树问题

Time Limit: 5 Sec  Memory Limit: 512 MB
Submit: 1025  Solved: 359
[Submit][Status][Discuss]

Description

给一个包含n个点,m条边的无向连通图。从顶点1出发,往其余所有点分别走一次并返回。
往某一个点走时,选择总长度最短的路径走。若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径(如路径A为1,32,11,路径B为1,3,2,11,路径B字典序较小。注意是序列的字典序的最小,而非路径中节点编号相连的字符串字典序最小)。到达该点后按原路返回,然后往其他点走,直到所有点都走过。
可以知道,经过的边会构成一棵最短路径树。请问,在这棵最短路径树上,最长的包含K个点的简单路径长度为多长?长度为该最长长度的不同路径有多少条?
这里的简单路径是指:对于一个点最多只经过一次的路径。不同路径是指路径两端端点至少有一个不同,点A到点B的路径和点B到点A视为同一条路径。

Input

第一行输入三个正整数n,m,K,表示有n个点m条边,要求的路径需要经过K个点。接下来输入m行,每行三个正整数Ai,Bi,Ci(1<=Ai,Bi<=n,1<=Ci<=10000),表示Ai和Bi间有一条长度为Ci的边。数据保证输入的是连通的无向图。

Output

输出一行两个整数,以一个空格隔开,第一个整数表示包含K个点的路径最长为多长,第二个整数表示这样的不同的最长路径有多少条。

Sample Input

6 6 4
1 2 1
2 3 1
3 4 1
2 5 1
3 6 1
5 6 1

Sample Output

3 4

HINT

对于所有数据n<=30000,m<=60000,2<=K<=n。

数据保证最短路径树上至少存在一条长度为K的路径。

2016.12.7新加数据一组by - wyx-150137






mdzz刷的这几道题就这道最水(相对),虽然代码也不短,但是套路呀


点分套路题,具体点分套路请见:普通套路 和  一般套路

若想拓展点分树套路请见:点分树套路


好了我们开始题解:

一共两问:

长度为k的最长路径  和  长度为k的权值长为最长权值的路径条数

千万要读清第二问!!!

第二问也要求长度为k!!!

以开始以为第二问不限制长度,以为这题两问两个套路,实际上都是不满足前缀减法的 一般套路

辣么熟悉点分治套路的同学就可以随便切了,不熟悉的建议先切上面普通套路 一般套路这两道题



代码:

/**************************************************************    Problem: 4016    User: **********    Language: C++    Result: Accepted    Time:944 ms    Memory:29716 kb****************************************************************/ #include<iostream>#include<algorithm>#include<cstring>#include<string>#include<cstdlib>#include<cmath>#include<cstdio>#include<climits>#include<queue>#include<stack>#include<map>#include<set>#define N 100010#define M 200020#define inf 1<<26#define pa pair<int,int>#define lowbit(x) x&(-x)using namespace std;int read(){    int x=0,f=1;char ch;    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;} int n,m,k,ans,ans1; int head[N],pos;struct edge{int to,next,c;}e[M];void add(int a,int b,int c){pos++;e[pos].to=b,e[pos].next=head[a],e[pos].c=c,head[a]=pos;} queue<int>Q;bool vis[N];int dis[N]; vector<pa>G[N];void spfa(){    for(int i=1;i<=n;i++)dis[i]=inf,vis[i]=0;    dis[1]=0,vis[1]=1;Q.push(1);    while(!Q.empty())    {        int u=Q.front();Q.pop();vis[u]=0;        int size=G[u].size();        for(int j=0;j<size;j++)        {            pa v=G[u][j];            if(dis[v.first]>dis[u]+v.second)            {                dis[v.first]=dis[u]+v.second;                if(!vis[v.first])                {                    vis[v.first]=1;                    Q.push(v.first);                }            }        }    }}void dfs(int u){    int size=G[u].size();vis[u]=1;    for(int i=0;i<size;i++)    {        int v=G[u][i].first,c=G[u][i].second;        if(vis[v]||dis[v]!=dis[u]+c)            continue;        add(u,v,c);add(v,u,c);dfs(v);    }} int size[N],sum,f[N],rt;void find_root(int u,int fa){    size[u]=1,f[u]=0;    for(int i=head[u];i;i=e[i].next)    {        int v=e[i].to;        if(vis[v]||v==fa)continue;        find_root(v,u);size[u]+=size[v];        f[u]=max(size[v],f[u]);    }f[u]=max(f[u],sum-size[u]);    if(f[rt]>f[u])rt=u;} struct node{int w,num;}d[N],p[N];int tot,t[N<<4][2],s[N<<4],all; void get_dep(int u,int fa){    p[++tot]=d[u];    for(int i=head[u];i;i=e[i].next)    {        int v=e[i].to;        if(v==fa||vis[v])continue;        d[v].num=d[u].num+1;        d[v].w=d[u].w+e[i].c;        get_dep(v,u);    }}void cal(int u,int nowl,int nown){    d[u].w=nowl,d[u].num=nown;    tot=0;get_dep(u,0);    for(int i=1;i<=tot;i++)        if(p[i].num<k)        {            int tmp=p[i].w+t[k-p[i].num][0];            if(tmp>ans)ans=tmp,ans1=t[k-p[i].num][1];            else if(tmp==ans)ans1+=t[k-p[i].num][1];        }        else if(p[i].num==k)        {            if(p[i].w>ans)ans=p[i].w,ans1=1;            else if(p[i].w==ans)ans1++;        }    for(int i=1;i<=tot;i++)        if(p[i].num<=k)        {            if(p[i].w>t[p[i].num][0])                t[p[i].num][0]=p[i].w,t[p[i].num][1]=1;            else if(p[i].w==t[p[i].num][0])t[p[i].num][1]++;            s[++all]=p[i].num;        }}void work(int u){    vis[u]=1;all=0;    for(int i=head[u];i;i=e[i].next)    {        int v=e[i].to;        if(vis[v])continue;        cal(v,e[i].c,1);    }for(int i=1;i<=all;i++)t[s[i]][0]=t[s[i]][1]=0;    for(int i=head[u];i;i=e[i].next)    {        int v=e[i].to;        if(vis[v])continue;        sum=size[v],rt=0;        find_root(v,0);work(rt);    }} void find_dep(int u,int fa){    p[++tot]=d[u];s[++all]=d[u].w;    for(int i=head[u];i;i=e[i].next)    {        int v=e[i].to;        if(v==fa||vis[v])continue;        d[v].w=d[u].w+e[i].c;        find_dep(v,u);    }} int main(){//  freopen("in.txt","r",stdin);//  freopen("my.txt","w",stdout);    n=read(),m=read(),k=read()-1;    for(int i=1;i<=m;i++)    {        int a=read(),b=read(),c=read();        G[a].push_back(make_pair(b,c));        G[b].push_back(make_pair(a,c));    }    for(int i=1;i<=n;i++)        sort(G[i].begin(),G[i].end());    spfa();for(int i=1;i<=n;i++)vis[i]=0;    dfs(1);for(int i=1;i<=n;i++)vis[i]=0;    sum=f[0]=n,rt=0;find_root(1,0);work(rt);    memset(vis,0,sizeof(vis));    printf("%d %d\n",ans,ans1);}


0 0
原创粉丝点击