hdu 6074 Phone Call

  O∧O http://acm.hdu.edu.cn/showproblem.php?pid=6074

  2017 Multi-University Training Contest - Team 4 - 1008

  fread真是其乐无穷呀!

  对于每个给出的ai,bi,ci,di,wi,记ai,bi的LCA为pi, 记ci,di的LCA为qi,

  首先根据wi来排序这些电话线

  使用并查集

  首先把ai到pi路径上未加入pi集合的点加入pi集合,然后把bi到pi路径上未加入pi集合的点加入pi集合,

  同样地,把ci到qi路径上未加入qi集合的点加入qi集合,di到qi路径上未加入qi集合的点加入qi集合。

  然后把如果qi未加入pi集合,那么把qi加入pi集合

  然后向上搜未加入集合点的时候,是可以跳跃着做的。

  

  这种代码,写一会想玩会手机。O∧O

 

624ms代码

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>

using namespace std;

namespace fastIO {  
    #define BUF_SIZE 100000  
    //fread -> read  
    bool IOerror = 0;  
    inline char nc() {  
        static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;  
        if(p1 == pend) {  
            p1 = buf;  
            pend = buf + fread(buf, 1, BUF_SIZE, stdin);  
            if(pend == p1) {  
                IOerror = 1;  
                return -1;  
            }  
        }  
        return *p1++;  
    }  
    inline bool blank(char ch) {  
        return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';  
    }  
    inline void read(int &x) {  
        char ch;  
        while(blank(ch = nc()));  
        if(IOerror)  
            return;  
        for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');  
    }  
    #undef BUF_SIZE  
};  
using namespace fastIO; 

typedef long long ll;

const int MAXN = 100010;
const int MAXQ = 200010;//查询数的最大值

//并查集部分
int F[MAXN];//需要初始化为-1
int find(int x)
{
    if(F[x] == -1)return x;
    return F[x] = find(F[x]);
}
void bing(int u,int v)
{
    int t1 = find(u);
    int t2 = find(v);
    if(t1 != t2)
        F[t1] = t2;
}
bool vis[MAXN];//访问标记
int ancestor[MAXN];//祖先

struct Edge
{
    int to,next;
}edge[MAXN*2];
int head[MAXN],tot;
void addedge(int u,int v)
{
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
}

struct Query
{
    int q,next;
    int index;//查询编号
}query[MAXQ*2];
int answer[MAXQ];//存储最后的查询结果,下标0~Q-1
int h[MAXQ];
int tt;
int Q;

void add_query(int u,int v,int index)
{
    query[tt].q = v;
    query[tt].next = h[u];
    query[tt].index = index;
    h[u] = tt++;
    query[tt].q = u;
    query[tt].next = h[v];
    query[tt].index = index;
    h[v] = tt++;
}

void init()
{
    tot = 0;
    memset(head,-1,sizeof(head));
    tt = 0;
    memset(h,-1,sizeof(h));
    memset(vis,false,sizeof(vis));
    memset(F,-1,sizeof(F));
    memset(ancestor,0,sizeof(ancestor));
}

void LCA(int u)
{
    ancestor[u] = u;
    vis[u] = true;
    for(int i = head[u];i != -1;i = edge[i].next)
    {
        int v = edge[i].to;
        if(vis[v])continue;
        LCA(v);
        bing(u,v);
        ancestor[find(u)] = u;
    }
    for(int i = h[u];i != -1;i = query[i].next)
    {
        int v = query[i].q;
        if(vis[v])
        {
            answer[query[i].index] = ancestor[find(v)];
        }
    }
}

const int M=100044;

struct PhoneLine
{
	int a,b,c,d,w,id;
} pl[M];

int n,m;
int fa[M],ansnum,jmp[M],num[M];
int stk[M],lstk,dep[M];
ll cst[M],anscst;

bool cmp(PhoneLine x,PhoneLine y)
{
	return x.w<y.w;
}

void getjmp(int rt,int pa,int depth)
{
	dep[rt]=depth;
	int i,j,v;
	jmp[rt]=pa;
	for(i=head[rt];i!=-1;i=edge[i].next)
	{
		v=edge[i].to;
		if(v==pa) continue;
		getjmp(v,rt,depth+1);
	}
}

void init2()
{
	int i,j;
	for(i=1;i<=n;i++)
	{
		fa[i]=i;
		num[i]=1;
		cst[i]=0;
	}
	ansnum=0; anscst=0;
	getjmp(1,0,1);
}

int fff(int x)
{
	if(fa[x]==x)
		return x;
	fa[x]=fff(fa[x]);
	return fa[x];
}

void merge(int a,int t,int w)
{
	int i,j,pa,pt,tmp;
	while(dep[a]>dep[t])
	{
		tmp=jmp[a];
		jmp[a]=jmp[t];
		pa=fff(a); pt=fff(t);
		if(pa!=pt)
		{
			fa[pa]=pt;
			num[pt]+=num[pa];
			cst[pt]+=cst[pa]+w;
		}
		a=tmp;
	}
}

void solve()
{
	int i,j,a,b,w,pa,pb,t,tmp;
	for(i=0;i<m;i++)
	{
		w=pl[i].w;
		t=answer[i*2];
		a=pl[i].a; b=pl[i].b;
		merge(a,t,w);
		merge(b,t,w);
		t=answer[i*2+1];
		a=pl[i].c; b=pl[i].d;
		merge(a,t,w);
		merge(b,t,w);
		a=answer[i*2]; b=answer[i*2+1];
		pa=fff(a); pb=fff(b);
		if(pa!=pb)
		{
			fa[pa]=pb;
			num[pb]+=num[pa];
			cst[pb]+=cst[pa]+w;
		}
	}
}

int main()
{
//	freopen("数据\\1008.in","r",stdin);
//	freopen("数据\\1008my.out","w",stdout);
	int i,j,u,v;
	int cas;
	read(cas);
	while(cas--)
    {
    	init();
    	read(n); read(m);
    	for(i=1;i<n;i++)
    	{
    		read(u); read(v);
    		addedge(u,v);
    		addedge(v,u);
		}
    	for(i=0;i<m;i++)
    	{
    		pl[i].id=i;
    		read(pl[i].a); read(pl[i].b); read(pl[i].c); read(pl[i].d); read(pl[i].w);
		}
		sort(pl,pl+m,cmp);
    	Q=2*m;
    	for(i=0;i<m;i++)
		{
			add_query(pl[i].a,pl[i].b,i*2);
			add_query(pl[i].c,pl[i].d,i*2+1);			
		}
		LCA(1);
//		printf("LCA finished\n");
		init2();
		solve();
		for(i=1;i<=n;i++)
			if(num[i]>ansnum)
			{
				ansnum=num[i];
				anscst=cst[i];
			}
		printf("%d %lld\n",ansnum,anscst);
	}
	return 0;
}

  

 

转载于:https://www.cnblogs.com/FxxL/p/7295689.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值