zoukankan      html  css  js  c++  java
  • ZOJ

    题意:一棵树上有m个红色结点,树的边有权值。q次查询,每次给出k个点,每次查询有且只有一次机会将n个点中任意一个点染红,令k个点中距离红色祖先距离最大的那个点的距离最小化。q次查询相互独立。
    分析:数据量很... 最大值最小化,二分搜答案。将ST表求lca的dfs函数加一点东西,求出每个点到其最近红色祖先的距离。check函数中,枚举到其红色祖先的距离超过下限的点。设非法点数为p,尝试将其距离通过一次染色缩小。具体做法是求出这p个点的lca,这个点就是要染红的点,因为只有修改这个点,才有可能将所有点的红祖先距离都缩减。若修改之后仍有结点非法,则check失败

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N=100005;
    struct node{
    	int v,next;
    	LL dis;
    }edges[N<<1];
    int head[N],e;
    int id[N]; //节点第一次被遍历的顺序
    LL dis[N]; //节点到根节点的距离
    LL rdis[N]; //距离最近的红色祖先的距离
    bool red[N];
    int RMQ[N*2][20];
    int curID;
    //F[i]表示第i个遍历的节点
    //B[i]表示F[i]在树中的深度
    int F[N*2],B[N*2];
    int n,m,Q,root;
    #include<bits/stdc++.h>
    using namespace std;
    ////////////////
    namespace IO {
    #define BUF_SIZE 100000
    #define OUT_SIZE 100000
    #define ll long long
        //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; }
                //{printf("IO error!
    ");system("pause");for (;;);exit(0);}
            }
            return *p1++;
        }
        inline bool blank(char ch) { return ch == ' ' || ch == '
    ' || ch == '
    ' || ch == '	'; }
        inline void read(int &x) {
            bool sign = 0; char ch = nc(); x = 0;
            for (; blank(ch); ch = nc());
            if (IOerror)return;
            if (ch == '-')sign = 1, ch = nc();
            for (; ch >= '0'&&ch <= '9'; ch = nc())x = x * 10 + ch - '0';
            if (sign)x = -x;
        }
        inline void read(ll &x) {
            bool sign = 0; char ch = nc(); x = 0;
            for (; blank(ch); ch = nc());
            if (IOerror)return;
            if (ch == '-')sign = 1, ch = nc();
            for (; ch >= '0'&&ch <= '9'; ch = nc())x = x * 10 + ch - '0';
            if (sign)x = -x;
        }
        inline void read(double &x) {
            bool sign = 0; char ch = nc(); x = 0;
            for (; blank(ch); ch = nc());
            if (IOerror)return;
            if (ch == '-')sign = 1, ch = nc();
            for (; ch >= '0'&&ch <= '9'; ch = nc())x = x * 10 + ch - '0';
            if (ch == '.') {
                double tmp = 1; ch = nc();
                for (; ch >= '0'&&ch <= '9'; ch = nc())tmp /= 10.0, x += tmp * (ch - '0');
            }
            if (sign)x = -x;
        }
        inline void read(char *s) {
            char ch = nc();
            for (; blank(ch); ch = nc());
            if (IOerror)return;
            for (; !blank(ch) && !IOerror; ch = nc())*s++ = ch;
            *s = 0;
        }
        inline void read(char &c) {
            for (c = nc(); blank(c); c = nc());
            if (IOerror) { c = -1; return; }
        }
        //fwrite->write
        struct Ostream_fwrite {
            char *buf, *p1, *pend;
            Ostream_fwrite() { buf = new char[BUF_SIZE]; p1 = buf; pend = buf + BUF_SIZE; }
            void out(char ch) {
                if (p1 == pend) {
                    fwrite(buf, 1, BUF_SIZE, stdout); p1 = buf;
                }
                *p1++ = ch;
            }
            void print(int x) {
                static char s[15], *s1; s1 = s;
                if (!x)*s1++ = '0'; if (x<0)out('-'), x = -x;
                while (x)*s1++ = x % 10 + '0', x /= 10;
                while (s1-- != s)out(*s1);
            }
            void println(int x) {
                static char s[15], *s1; s1 = s;
                if (!x)*s1++ = '0'; if (x<0)out('-'), x = -x;
                while (x)*s1++ = x % 10 + '0', x /= 10;
                while (s1-- != s)out(*s1); out('
    ');
            }
            void print(ll x) {
                static char s[25], *s1; s1 = s;
                if (!x)*s1++ = '0'; if (x<0)out('-'), x = -x;
                while (x)*s1++ = x % 10 + '0', x /= 10;
                while (s1-- != s)out(*s1);
            }
            void println(ll x) {
                static char s[25], *s1; s1 = s;
                if (!x)*s1++ = '0'; if (x<0)out('-'), x = -x;
                while (x)*s1++ = x % 10 + '0', x /= 10;
                while (s1-- != s)out(*s1); out('
    ');
            }
            void print(double x, int y) {
                static ll mul[] = { 1,10,100,1000,10000,100000,1000000,10000000,100000000,
                    1000000000,10000000000LL,100000000000LL,1000000000000LL,10000000000000LL,
                    100000000000000LL,1000000000000000LL,10000000000000000LL,100000000000000000LL };
                if (x<-1e-12)out('-'), x = -x; x *= mul[y];
                ll x1 = (ll)floor(x); if (x - floor(x) >= 0.5)++x1;
                ll x2 = x1 / mul[y], x3 = x1 - x2 * mul[y]; print(x2);
                if (y>0) { out('.'); for (size_t i = 1; i<y&&x3*mul[i]<mul[y]; out('0'), ++i); print(x3); }
            }
            void println(double x, int y) { print(x, y); out('
    '); }
            void print(char *s) { while (*s)out(*s++); }
            void println(char *s) { while (*s)out(*s++); out('
    '); }
            void flush() { if (p1 != buf) { fwrite(buf, 1, p1 - buf, stdout); p1 = buf; } }
            ~Ostream_fwrite() { flush(); }
        }Ostream;
        inline void print(int x) { Ostream.print(x); }
        inline void println(int x) { Ostream.println(x); }
        inline void print(char x) { Ostream.out(x); }
        inline void println(char x) { Ostream.out(x); Ostream.out('
    '); }
        inline void print(ll x) { Ostream.print(x); }
        inline void println(ll x) { Ostream.println(x); }
        inline void print(double x, int y) { Ostream.print(x, y); }
        inline void println(double x, int y) { Ostream.println(x, y); }
        inline void print(char *s) { Ostream.print(s); }
        inline void println(char *s) { Ostream.println(s); }
        inline void println() { Ostream.out('
    '); }
        inline void flush() { Ostream.flush(); }
    #undef ll
    #undef OUT_SIZE
    #undef BUF_SIZE
    };
    using namespace IO;
    
    void init()
    {
        e = 0; curID = 0;
        memset(head,-1,sizeof(head));
    	memset(red,0,sizeof(red));
    }
    
    void AddEdge (int u,int v,LL w)
    {
    	edges[e].v=v;
    	edges[e].dis=w;
    	edges[e].next=head[u];
    	head[u]=e++;
    }
    
    void DFS (int u,int p,int Dep,LL d)
    {
    	int i,v;
    	if(red[u]) d=0;
    	curID++;
    	rdis[u] = d;
    	F[curID]=u;
    	B[curID]=Dep;
    	id[u]=curID;
    	for (i=head[u];i!=-1;i=edges[i].next){
    		v=edges[i].v;
    		if (v==p) continue;
    		dis[v]=dis[u] + edges[i].dis;
    		DFS(v,u,Dep+1,d+edges[i].dis);
    		curID++;
    		F[curID]=u;
    		B[curID]=Dep;
    	}
    }
    
    void initRMQ ()
    {
    	int i,j,x,y;
    	for (i=1;i<=curID;i++)
    		RMQ[i][0]=i;
    	for (j=1;(1<<j)<=curID;j++)
    		for (i=1;i+(1<<j)-1<=curID;i++){
    			x=RMQ[i][j-1];
    			y=RMQ[i+(1<<(j-1))][j-1];
    			RMQ[i][j]=B[x]<B[y]?x:y;
    		}
    }
    
    int getLCA (int a,int b)
    {
    	int k,x,y;
    	a=id[a];b=id[b];
    	if (a>b)
    		k=a,a=b,b=k;
    	k = 31 - __builtin_clz(b-a+1);
    	x=RMQ[a][k];
    	y=RMQ[b-(1<<k)+1][k];
    	return B[x]<B[y]?F[x]:F[y];
    }
    
    int qq[N],cnt;
    int vz[N];
    
    bool check(LL &x)
    {
    	int all =0;
    	for(int i=0;i<cnt;++i){             //枚举超过限制的结点
    		if(rdis[qq[i]]>x){
    			vz[all++] = qq[i];
    		}
    	}
    	if(all==0) return true;
    	int lca = vz[0];
    	for(int i=0;i<all;++i){             //求出所有非法结点的lca,这个lca就是要染色的点
    		lca = getLCA(lca,vz[i]);
    	}
    	LL mx = 0;
    	for(int i=0;i<all;++i){             //查看最长距离
            if(dis[vz[i]]-dis[lca]>x) return false;
    	}
    	return true;
    }
    
    int main()
    {
    	#ifndef ONLINE_JUDGE
            freopen("in.txt","r",stdin);
            freopen("out.txt","w",stdout);
        #endif
        int T; read(T);
        while(T--){
    		int n,M,Q;
    		int u,v; LL w;
    		LL up = 0;
            init();
    		read(n), read(M), read(Q);
            //scanf("%d %d %d",&n,&M,&Q);
    		for(int i=1;i<=M;++i){
    			read(u);
    			red[u] = 1;
            }
    		red[1] = 1;
            for(int i=1;i<n;++i){
    			//scanf("%d %d %lld",&u,&v,&w);
    			read(u), read(v), read(w);
    			AddEdge(u,v,w);
    			AddEdge(v,u,w);
    			up += w;
            }
    		DFS(1,0,0,0);
    		initRMQ();
    		while(Q--){
    			int k; 	read(k);//scanf("%d",&k);
    			cnt = k;
    			for(int i=0;i<k;++i){
    				read(qq[i]);
    				//scanf("%d",&qq[i]);
    			}
    			LL L =0,R = up,mid,ans = up;
    			while(L<=R){
    				mid = (L+R)>>1;
    				if(check(mid)){
    					ans = mid;
    					R = mid-1;
    				}
    				else L =mid+1;
    			}
    			println(ans);
    			//printf("%lld
    ",ans);
    		}
        }
        return 0;
    }
    
    为了更好的明天
  • 相关阅读:
    JS刷新当前页面的几种方法总结
    C#实现,C++实现,JS实现 阿拉伯数字金额转换为中文大写金额
    SQL server 生成数据字典
    jquery操作复选框(checkbox)的一些小技巧总结
    HTML中的几种空格
    C#几个经常用到的字符串截取
    关于百度地图API和jqGrid踩到的坑
    SQL常见问题积累
    JS实用小函数 数据是否合法或存在 获取当前日期时间
    vs2010 学习Silverlight学习笔记(13):数据与通信之WCF
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9676674.html
Copyright © 2011-2022 走看看