hdu4812 D Tree

来源:互联网 发布:excel数组 编辑:程序博客网 时间:2024/06/08 07:13



Problem Description
There is a skyscraping tree standing on the playground of Nanjing University of Science and Technology. On each branch of the tree is an integer (The tree can be treated as a connected graph with N vertices, while each branch can be treated as a vertex). Today the students under the tree are considering a problem: Can we find such a chain on the tree so that the multiplication of all integers on the chain (mod 106 + 3) equals to K?
Can you help them in solving this problem?
 

Input
There are several test cases, please process till EOF.
Each test case starts with a line containing two integers N(1 <= N <= 105) and K(0 <=K < 106 + 3). The following line contains n numbers vi(1 <= vi < 106 + 3), where vi indicates the integer on vertex i. Then follows N - 1 lines. Each line contains two integers x and y, representing an undirected edge between vertex x and vertex y.
 

Output
For each test case, print a single line containing two integers a and b (where a < b), representing the two endpoints of the chain. If multiply solutions exist, please print the lexicographically smallest one. In case no solution exists, print “No solution”(without quotes) instead.
For more information, please refer to the Sample Output below.
 

Sample Input
5 60
2 5 2 3 3
1 2
1 3
2 4
2 5
5 2
2 5 2 3 3
1 2
1 3
2 4
2 5
 

Sample Output
3 4
No solution

分析:
这道题就是有点难码
我们还是像朴素的点分治一样,遍历整棵树
对于每条路径,我们要用map记录一下每种长度对应的最小路径端点
这样在计算路径的时候,直接维护答案即可

tip

在hdu上一直是T,搞得很烦

//这里写代码片#include<cstdio>#include<cstring>#include<iostream>#define ll long longusing namespace std;const int INF=1e9;const int N=100010;const int M=1000010;const int mod=1000003;int f[N],id[N],sz[N],root,sum,tt,ansl,ansr;int st[N],tot=0,n;ll K,v[N],inv[M],d[M],mp[M];struct node{    int x,y,nxt;};node way[N<<1];bool vis[N];void add(int u,int w){    tot++;    way[tot].x=u;way[tot].y=w;way[tot].nxt=st[u];st[u]=tot;}void getroot(int now,int fa){    f[now]=0;    sz[now]=1;    for (int i=st[now];i;i=way[i].nxt)        if (way[i].y!=fa&&!vis[way[i].y])        {            getroot(way[i].y,now);            sz[now]+=sz[way[i].y];            f[now]=max(f[now],sz[way[i].y]);        }    f[now]=max(f[now],sum-sz[now]);    if (f[now]<f[root]) root=now;}void getdeep(int now,int fa,ll z){    d[++tt]=(z*v[now])%mod;    id[tt]=now;    for (int i=st[now];i;i=way[i].nxt)        if (way[i].y!=fa&&!vis[way[i].nxt])            getdeep(way[i].y,now,(z*v[now])%mod);}void update(int x,int y,int z)             //x是两条路径的连接点 {    int tmp=mp[inv[z*v[x]%mod]*K%mod];     //z*v[x]    if (!tmp) return;    if (y>tmp) swap(y,tmp);    if (y<ansl || (y==ansl&&tmp<ansr)) ansl=y,ansr=tmp;}void dfs(int now){    vis[now]=1;    mp[1]=now;    for (int i=st[now];i;i=way[i].nxt)        if (!vis[way[i].y])        {            tt=0;            getdeep(way[i].y,now,1);            for (int j=1;j<=tt;j++) update(now,id[j],d[j]);    //计算             for (int j=1;j<=tt;j++) if ( !mp[d[j]] || mp[d[j]]>id[j] ) mp[d[j]]=id[j];        }    mp[1]=0;    for (int i=st[now];i;i=way[i].nxt)        if (!vis[way[i].y])        {            tt=0;            getdeep(way[i].y,now,1);            for (int j=1;j<=tt;j++) mp[d[j]]=0;    //去重         }    for (int i=st[now];i;i=way[i].nxt)        if (!vis[way[i].y])        {            root=0; sum=sz[way[i].y];            getroot(way[i].y,0);            dfs(root);        }}int main(){    inv[1]=1; inv[0]=1;    for (int i=2;i<mod;i++) inv[i]=((mod-mod/i)%mod*inv[mod%i]%mod)%mod;    while (scanf("%d%I64d",&n,&K)!=EOF)    {        memset(st,0,sizeof(st)); tot=0;        memset(vis,0,sizeof(vis));        ansl=ansr=M;        for (int i=1;i<=n;i++) scanf("%I64d",&v[i]);        for (int i=1;i<n;i++)        {            int u,w;            scanf("%d%d",&u,&w);            add(u,w); add(w,u);        }        sum=n; f[0]=N; root=0;        getroot(1,0);        dfs(root);        if (ansl==M) puts("No solution");        else printf("%d %d\n",ansl,ansr);    }}
原创粉丝点击