zoukankan      html  css  js  c++  java
  • CodeForces701E DFS

    http://codeforces.com/problemset/problem/701/E

    一个显而易见的方法是考虑点的贡献,一次dfs记录到所有根节点不考虑匹配的答案,再一次dfs反向推出答案 

    #include <map>
    #include <set>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <string>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    using namespace std;
    const int MAXBUF=10000;char buf[MAXBUF],*ps=buf,*pe=buf+1;
    inline bool isdigit(const char& n) {return (n>='0'&&n<='9');}
    inline void rnext(){if(++ps==pe)pe=(ps=buf)+fread(buf,sizeof(char),sizeof(buf)/sizeof(char),stdin);}
    template <class T> inline bool in(T &ans){
    #ifdef VSCode
    ans=0;T f=1;register char c;
    do{c=getchar();if ('-'==c)f=-1;}while(!isdigit(c)&&c!=EOF);
    if(c==EOF)return false;do{ans=(ans<<1)+(ans<<3)+c-48;
    c=getchar();}while(isdigit(c)&&c!=EOF);ans*=f;return true;
    #endif
    #ifndef VSCode 
    ans =0;T f=1;if(ps==pe)return false;do{rnext();if('-'==*ps)f=-1;} 
    while(!isdigit(*ps)&&ps!=pe);if(ps==pe)return false;do{ans=(ans<<1)+(ans<<3)+*ps-48;
    rnext();}while(isdigit(*ps)&&ps!=pe);ans*=f;return true;
    #endif
    }const int MAXOUT=10000;
    char bufout[MAXOUT], outtmp[50],*pout = bufout, *pend = bufout+MAXOUT;
    inline void write(){fwrite(bufout,sizeof(char),pout-bufout,stdout);pout = bufout;}
    inline void out_char(char c){*(pout++)=c;if(pout==pend)write();}
    inline void out_str(char *s){while(*s){*(pout++)=*(s++);if(pout==pend)write();}}
    template <class T>inline void out_int(T x) {if(!x){out_char('0');return;}
    if(x<0)x=-x,out_char('-');int len=0;while(x){outtmp[len++]=x%10+48;x/=10;}outtmp[len]=0;
    for(int i=0,j=len-1;i<j;i++,j--) swap(outtmp[i],outtmp[j]);out_str(outtmp);}
    template<typename T, typename... T2>
    inline int in(T& value, T2&... value2) { in(value); return in(value2...); }
    #define For(i, x, y) for(int i=x;i<=y;i++)  
    #define _For(i, x, y) for(int i=x;i>=y;i--)
    #define Mem(f, x) memset(f,x,sizeof(f))  
    #define Sca(x) scanf("%d", &x)
    #define Scl(x) scanf("%lld",&x);  
    #define Pri(x) printf("%d
    ", x)
    #define Prl(x) printf("%lld
    ",x);  
    #define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
    #define LL long long
    #define ULL unsigned long long  
    #define mp make_pair
    #define PII pair<int,int>
    #define PIL pair<int,long long>
    #define PLL pair<long long,long long>
    #define pb push_back
    #define fi first
    #define se second 
    #define Vec Point
    typedef vector<int> VI;
    const double eps = 1e-9;
    const int maxn = 2e5 + 10;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9 + 7; 
    int N,K,temp,cnt;
    bool sp[maxn];
    LL head[maxn],MAX[maxn],id[maxn],sum[maxn],ans[maxn];
    struct Edge{
        int to,next;
    }edge[maxn * 2];
    void init(){Mem(head,0); cnt = 0;}
    void add(int u,int v){edge[++cnt].to = v; edge[cnt].next = head[u];head[u] = cnt;}
    LL dfs(int x,int last){
        sum[x] = 0;
        for(int i = head[x] ; i; i = edge[i].next){
            int v = edge[i].to;
            if(v == last) continue;
            int t = dfs(v,x);
            if(t > MAX[x]){
                MAX[x] = t;
                id[x] = v;
            }
            sum[x] += t;
            ans[x] += ans[v];
        }
        ans[x] += sum[x];
        sum[x] += sp[x];
        return sum[x];
    }
    LL getans(int x,int c){
        sum[x] -= c;
        MAX[x] -= c;
        if(MAX[x] * 2 <= sum[x]){
            return ans[x];
        }else{
            int v = id[x];
            return ans[x] - ans[v] - sum[v] + getans(v,sum[x] - MAX[x] + c) + sum[x] - MAX[x] + c;
        }
    }
    LL solve(){
        int root = 1;
        dfs(root,-1);
        // For(i,1,N){
        //     cout << i << ":" << sum[i] << " " << MAX[i] << endl;
        // }
        return getans(root,0);
    }
    int main()
    {
        in(N,K);
        For(i,1,2 * K){
            in(temp);
            sp[temp] = 1;
        }
        For(i,1,N - 1){
            int u,v; in(u,v);
            add(u,v); add(v,u);
        }
        Prl(solve());
        #ifdef VSCode
        write();
        system("pause");
        #endif
        return 0;
    }
    View Code

    这并不是很好写,另一个不显而易见但是很好写很好对的方法是考虑边的贡献,一条边两边的点分别是x和2K - x,由于路线尽可能的长,较小的那一边一定要加上较大的那一边,所以每条边经过一次,同时更新ans即可

    #include <map>
    #include <set>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <string>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    using namespace std;
    const int MAXBUF=10000;char buf[MAXBUF],*ps=buf,*pe=buf+1;
    inline bool isdigit(const char& n) {return (n>='0'&&n<='9');}
    inline void rnext(){if(++ps==pe)pe=(ps=buf)+fread(buf,sizeof(char),sizeof(buf)/sizeof(char),stdin);}
    template <class T> inline bool in(T &ans){
    #ifdef VSCode
    ans=0;T f=1;register char c;
    do{c=getchar();if ('-'==c)f=-1;}while(!isdigit(c)&&c!=EOF);
    if(c==EOF)return false;do{ans=(ans<<1)+(ans<<3)+c-48;
    c=getchar();}while(isdigit(c)&&c!=EOF);ans*=f;return true;
    #endif
    #ifndef VSCode 
    ans =0;T f=1;if(ps==pe)return false;do{rnext();if('-'==*ps)f=-1;} 
    while(!isdigit(*ps)&&ps!=pe);if(ps==pe)return false;do{ans=(ans<<1)+(ans<<3)+*ps-48;
    rnext();}while(isdigit(*ps)&&ps!=pe);ans*=f;return true;
    #endif
    }const int MAXOUT=10000;
    char bufout[MAXOUT], outtmp[50],*pout = bufout, *pend = bufout+MAXOUT;
    inline void write(){fwrite(bufout,sizeof(char),pout-bufout,stdout);pout = bufout;}
    inline void out_char(char c){*(pout++)=c;if(pout==pend)write();}
    inline void out_str(char *s){while(*s){*(pout++)=*(s++);if(pout==pend)write();}}
    template <class T>inline void out_int(T x) {if(!x){out_char('0');return;}
    if(x<0)x=-x,out_char('-');int len=0;while(x){outtmp[len++]=x%10+48;x/=10;}outtmp[len]=0;
    for(int i=0,j=len-1;i<j;i++,j--) swap(outtmp[i],outtmp[j]);out_str(outtmp);}
    template<typename T, typename... T2>
    inline int in(T& value, T2&... value2) { in(value); return in(value2...); }
    #define For(i, x, y) for(int i=x;i<=y;i++)  
    #define _For(i, x, y) for(int i=x;i>=y;i--)
    #define Mem(f, x) memset(f,x,sizeof(f))  
    #define Sca(x) scanf("%d", &x)
    #define Scl(x) scanf("%lld",&x);  
    #define Pri(x) printf("%d
    ", x)
    #define Prl(x) printf("%lld
    ",x);  
    #define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
    #define LL long long
    #define ULL unsigned long long  
    #define mp make_pair
    #define PII pair<int,int>
    #define PIL pair<int,long long>
    #define PLL pair<long long,long long>
    #define pb push_back
    #define fi first
    #define se second 
    #define Vec Point
    typedef vector<int> VI;
    const double eps = 1e-9;
    const int maxn = 2e5 + 10;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9 + 7; 
    int N,K,temp,cnt;
    bool sp[maxn];
    LL head[maxn],MAX[maxn],id[maxn],sum[maxn],ans[maxn],Ans;
    struct Edge{
        int to,next;
    }edge[maxn * 2];
    void init(){Mem(head,0); cnt = 0;}
    void add(int u,int v){edge[++cnt].to = v; edge[cnt].next = head[u];head[u] = cnt;}
    LL dfs(int x,int last){
        sum[x] = sp[x];
        for(int i = head[x] ; i; i = edge[i].next){
            int v = edge[i].to;
            if(v == last) continue;
            int t = dfs(v,x);
            Ans += min(t,2 * K - t);
            sum[x] += t;
        }
        return sum[x];
    }
    LL solve(){
        int root = 1;
        dfs(root,-1);
        return Ans;
    }
    int main()
    {
        in(N,K);
        For(i,1,2 * K){
            in(temp);
            sp[temp] = 1;
        }
        For(i,1,N - 1){
            int u,v; in(u,v);
            add(u,v); add(v,u);
        }
        Prl(solve());
        #ifdef VSCode
        write();
        system("pause");
        #endif
        return 0;
    }
  • 相关阅读:
    Android之rild进程启动源码分析
    ListView使用详解,listActivity使用方法
    打开其他android应用代码
    Android剖析和运行机制
    自定义Dialog(图片,文字说明,单选按钮)----类ListPreference实现(2)
    Internet采用哪种网络协议?该协议的主要层次结构?Internet物理地址和IP地址转换采用什么协议?
    引用与指针有什么区别?
    在C/C++中static有什么用途?
    软件验收测试包括
    自底向上集成
  • 原文地址:https://www.cnblogs.com/Hugh-Locke/p/9499721.html
Copyright © 2011-2022 走看看