noip2013day1题解

来源:互联网 发布:linux的syslog开启 编辑:程序博客网 时间:2024/05/24 06:02

转圈游戏:

# include <iostream># include <algorithm># include <string># include <cstring># include <cmath># include <ctime># include <cstdio># include <queue>using namespace std; typedef long long ll;long long n,m,k,x;  ll Read(){ll i=0,f=1;char c=getchar();whi

#include<iostream> #include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>using namespace std;#define MAXN 10010#define MAXM 50010#define MAXD 22#define inf 200000int father[MAXN],n,m,q;bool visit[MAXN];int up[MAXN][MAXD],Min[MAXN][MAXD],h[MAXN];struct saver{    int s,t,d;} e[MAXM]; int cmp(saver a,saver b){    return a.d>b.d;} //并查集void init()   {    for(int i=0; i<MAXN; i++)father[i]=i;}int Find(int x){    if(x==father[x])return father[x];    else    {        father[x]=Find(father[x]);        return father[x];    }}void Union(int x,int y){    int fx=Find(x);    int fy=Find(y);    if(fx!=fy)    {        father[fx]=fy;    }}//处理最大生成树后的边的关系struct edge{    edge *next;    int t,d;    edge()    {        next=NULL;    }}*head[MAXN];void Add(int s,int t,int d){    edge *p=new(edge);    p->t=t,p->d=d,p->next=head[s];    head[s]=p;}void AddEdge(int s,int t,int d){    Add(s,t,d);    Add(t,s,d);}//一个dfs过程,对于和v在一棵树上的所有结点计算其在树中的高度以及up[i][0]和Min[i][0]void BuildTree(int v){    visit[v]=true;    for(edge *p=head[v]; p; p=p->next)    {        if(!visit[p->t])        {            up[p->t][0]=v;            Min[p->t][0]=p->d;            h[p->t]=h[v]+1;            BuildTree(p->t);        }    }}//得到u和v两分支高度相同的节点,在此基础上开始倍增int Move(int &v,int H){    int rec = inf;    for(int i=MAXD-1; i>=0; i--)    {        if(h[up[v][i]]>=H)        {            rec=min(rec,Min[v][i]);            v=up[v][i];        }    }    return rec;}//倍增算法实现询问u和v路径上最小值int Query(int u,int v){    if(Find(u)!=Find(v))return -1;    int rec = inf;    if(h[u]!=h[v])rec=h[u]>h[v]?Move(u,h[v]):Move(v,h[u]);    if(u==v) return rec;    for(int i=MAXD-1; i>=0; i--)    {        if(up[u][i]!=up[v][i])        {            rec=min(rec,min(Min[u][i],Min[v][i]));            u=up[u][i];            v=up[v][i];        }    }    rec=min(rec,min(Min[u][0],Min[v][0]));    return rec;}int main(){     //输入   //freopen("truck.in", "r", stdin);    //freopen("truck.out", "w", stdout);    memset(head,0,sizeof(head));    memset(up,0,sizeof(up));    scanf("%d %d",&n,&m);    for(int i=0; i<m; i++)scanf("%d %d %d",&e[i].s,&e[i].t,&e[i].d);        //排序后生产最大生成树构成的森林    sort(e,e+m,cmp);    init();    for(int i=0; i<m; i++)    {        if(Find(e[i].s)!=Find(e[i].t))        {            Union(e[i].s,e[i].t);            AddEdge(e[i].s,e[i].t,e[i].d);        }    }        //初始化每一个结点的up[i][0]和Min[i][0],并计算结点在树中高度    memset(visit,false,sizeof(visit));    for(int i=1; i<=n; i++)    {        if(!visit[i])        {            h[i]=0;            BuildTree(i);            Min[i][0]=inf;            up[i][0]=i;        }    }        //预处理出up[i][j]和Min[i][j]数组    for(int i=1; i<MAXD; i++)    {        for(int j=1; j<=n; j++)        {            up[j][i]=up[up[j][i-1]][i-1];            Min[j][i]=min(Min[j][i-1],Min[up[j][i-1]][i-1]);        }    }        //处理询问    scanf("%d",&q);    while(q--)    {        int u,v;        scanf("%d %d",&u,&v);        printf("%d\n",Query(u,v));    }    return 0;} 


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 苹果6s降频怎么办 0首付手机还不起怎么办 乐才app登录不上怎么办 买了笔记本网要怎么办? 电脑连接不上网络怎么办 电脑上没网络了怎么办 手机返回键不好使怎么办 笔记本无线网连接受限怎么办 魅族打电话图标没有了怎么办 京东价格保护后发票怎么办 淘宝未满十八岁怎么办 SVN提交时代码冲突怎么办 京东自营没货了怎么办 京东下了单 没货怎么办 万达广场购物卡怎么办 京东白条没额度怎么办 京东退款还收到货怎么办 退货不想要货了怎么办 安装微擎创建数据库失败怎么办 tp文件损坏或丢失怎么办 手机QQ启动有问题应该怎么办 微信网页版页面巨大怎么办 魔兽军团烹饪食谱扔了怎么办 赴港旅游网上签证怎么办了? 美团商家入住没有营业执照怎么办 团购房子不想要怎么办 乐视液晶屏坏了怎么办 wifi盒子插上网线然后怎么办 在泰国手机坏了怎么办 朋友在泰国手机关机怎么办 qq上转账转错了怎么办 扣扣转账转错了怎么办 到付快递签收了怎么办 京东白条消费了怎么办 确认收货点错了怎么办 小米6后盖缝隙大怎么办 苹果6splus电池不耐用怎么办 苹果一朵云加箭头下载不了怎么办 苹果8p信号不好怎么办 苹果8p像素不好怎么办 美版iphonex有锁怎么办