2017GDCPC题解(未完)

这篇博客详细解析了2017年GDCPC比赛中的若干问题,包括Open Box、Power Grid、Stockpile等。针对每个问题,博主提供了详细的题目大意和算法思路,涉及模拟、最短路径、分段函数计算等算法。虽然部分题目如Boggle Game和Coup未给出具体解析,但博主分享了其他问题的解决办法,如使用SPFA判断负环、树形DP等。
摘要由CSDN通过智能技术生成

以下代码均没有经过数据验证,若有不正确的地方,劳烦各位dalao指出

Problem A:Open Box

题目大意:

给一把锁,锁的密码是9394,输入4个字符表示该锁每一位密码现在所在的位置,问最少需要多少次操作可以到9394,密码锁是旋转的0-9成环。

算法思路:

水题,模拟一下操作可以往后转或者往前转,选最优的就好了。

/*
@resources: GDCPC 2017 A
@date: 2017-05-09
@author: QuanQqqqq
@algorithm: yy
*/
#include <bits/stdc++.h>

using namespace std;

int code[] = {9,3,9,4};

int change(int a,int b){
    int t1,t2;
    if(a > b){
        t1 = a - b;
        t2 = b + 10 - a;
    } else {
        t1 = b - a;
        t2 = a + 10 - b;
    }
    return min(t1,t2);
}

int main(){
    char ch[10];
    int T,ans,cas = 1;
    scanf("%d",&T);
    getchar();
    while(T--){
        gets(ch);
        ans = 0;
        for(int i = 0;i < 4;i++){
            ans += change(ch[i] - '0',code[i]);
        }
        printf("Case #%d: %d\n",cas++,ans);
    }
}

Problem B:Power Grid

题目大意:

有n个城市,m条路径,每一个城市每到达一次可以提供ei点电量,每次从wi城市到vi城市需要花费wi点电量,两个城市之间会有多种路线,现在问你任意选取一个城市作起始点,他会提供给你该城市所提供的ei点电量,问是否可以访问完所有城市。城市可以重复访问。

算法思路:

题目好像没有说,自己可以访问自己花费多少电力(我们假设这种情况存在。。)。
首先需要访问完所有城市,那么所有城市一定要连通,如果不连通,则输出NO。

城市之间可以多次访问,在联通的条件下,如果经过某些城市之后回到该点,所拥有的电量增加,则说明一定可以跑完整幅图(因为你只要一直充电。。。然后等到足够电的时候开始跑图就好了)
这种情况需要用SPFA来判一下负环,如果花费的路径出现负环的话,则说明一定可以跑完整幅图,则输出YES。

以上特殊情况都不存在的话,先跑一个整幅图的最短路,然后,对于每一个点都初始化他的Ei点电量,然后开始简单状压DP,其他点都初始化成-1,对于每一个点有
如果满足dp[s][i] - g[i][j] >= 0
则有dp[s ^ (1 << (j - 1))][j] = max(dp[s ^ (1 << (j - 1))][j],dp[s][i] - g[i][j] + e[i]);
然后dp完毕后,再看dp[0][1 -> n]这些点,有没有存在大于等于0的即可,存在则为YES,不存在为NO。

/*
@resources: GDCPC 2017 B
@date: 2017-05-11
@author: QuanQqqqq
@algorithm: dp spfa
*/
#include <bits/stdc++.h>

#define ll long long
#define MAXN 20

using namespace std;

const ll INF = (1LL << 33);

ll dp[1 << 17][MAXN];
ll e[MAXN];
ll mapp[MAXN][MAXN];
ll d[MAXN];
ll g[MAXN][MAXN];
ll in[MAXN];
bool mark[MAXN];
bool flag[MAXN];
int n;
queue<int> q;

void init(){
    memset(dp,-1,sizeof(dp));
    memset(flag,false,sizeof(flag));
    for(int i = 0;i < MAXN;i++){
        for(int j = 0;j < MAXN;j++){
            if(i == j){
                mapp[i][j] = 0;
                g[i][j] = 0;
            } else {
                g[i][j] = INF;
                mapp[i][j] = INF;
            }
        }
    }
}

void dfs(int v){
    mark[v] = true;
    for(int i = 1;i <= n;i++){
        if(!mark[i]){
            dfs(i);
        }
    }
}

bool spfa(int u){
    memset(mark,false,sizeof(mark));
    memset(in,0,sizeof(in));
    for(int i = 0;i < MAXN;i++){
        d[i] = INF;
    }
    while(!q.empty()){
        q.pop();
    }
    int v;
    d[u] = 0;
    mark[u] = true;
    q.push(u);
    while(!q.empty()){
        v = q.front();
        mark[v] = false;
        for(int i = 1;i <= n;i++){
            if(d[v] + mapp[v][i] < d[i] && i != v){
                d[i] = d[v] + mapp[v][i];
                if(in[v] >= 1){
                    d[i] -= e[v];
                }
                if(!mark[i]){
                    in[i]++;
                    if(in[i] > n){
                        return true;
                    }
                    mark[i] = true;
                    q.push(i);
                }
            }
        }
        q.pop();
    }
    for(int i = 1;i <= n;i++){
        g[u][i] = d[i];
    }
    return false;
}

int main(){
    int T,u,v,m,cas = 1;
    ll w;
    bool con,ans;
    scanf("%d",&T);
    while(T--){
        init();
        scanf("%d %d",&n,&m);
        for(int i = 1;i <= n;i++){
            scanf("%lld",&e[i]);
        }
        ans = con = false;
        for(int i = 1;i <= m;i++){
            scanf("%d %d %lld",&u,&v,&w);
            u++,v++;
            if(v == u){ //该点无限充电 
                if(w < e[v]){
                    flag[v] = true;
                }
            }
            mapp[u][v] = min(mapp[u][v],w);
        }
        printf("Case #%d: ",cas++);
        for(int i = 1;i <= n;i++){
            memset(mark,0,sizeof(mark));
            dfs(i);
            int total = 0;
            for(int j = 1;j <= n;j++){
                if(mark[i]){
                    total++;
                }
            }
            if(total == n){
                con = true;
                if(flag[i]){
                    ans = true;
                }
            }
        }
        if(!con){ //不连通 
            printf("No\n");
            continue;
        }
        if(ans){ //某点无限充电,且该点可以遍历整个图 
            printf("Yes\n");
            continue;
        }
        for(int i = 1;i <= n;i++){
            if(spfa(i)){
                ans = true;
                break;
            } 
        }
        if(ans){ //存在负环 
            printf("Yes\n");
            continue;
        }
        for(int i = 1;i <= n;i++){
            dp[((1 << n) - 1) ^ (1 << (i - 1))][i] = e[i];
        }
        for(int s = (1 << n) - 2;s >= 0;s--){
            for(int i = 1;i <= n;i++){
                for(int j = 1;j <= n;j++){
                    if(s & (1 << (j - 1))){
                        if(dp[s][i] - g[i][j] >= 0){
                            dp[s ^ (1 << (j - 1))][j] = max(dp[s ^ (1 << (j - 1))][j],dp[s][i] - g[i][j] + e[i]);
                        }
                    }
                }
            }   
        }
        for(int i = 1;i <= n;i++){
            if(dp[0][i] >= 0){
                ans = true;
            }
        }
        if(ans){
            printf("Yes\n");
        } else {
            printf("No\n");
        }
    }
}
/*
3
3 2
5 3 3
0 1 5
1 2 3
2 1
10 0
0 1 20
4 5
10 5 0 0
0 1 20
0 1 5
1 2 5
2 1 5
1 3 5
*/

Problem C:Stockpile

题目大意:

有两种分段函数,一种是对应PUT,一种对应CALL。
先输入三个数,Ci,Pi,Ki,分别对应某函数
PUT的时候
对于P > X的情况,有函数Y = (P - X) * K - C
对于P <= X的情况,有函数Y = -C
CALL的时候
对于X > P的情况,有函数Y = (X - P) * K - C
对于X <= P的情况,有函数Y = -C
现在需要你将所有函数合并变成分段函数。
总函数的条数为10^6
测试数据为2000组

算法思路:

其实计算是O(n)的时间复杂度对这题也是超时的。O(n*T)。。。
赛场上没看题。
对于这种分段,其实每一个分段点就只有P这个点,将所有P点弄成集合,sort一下离散化去重点。
接下来个人做法有点复杂,因为很明显对于每一个函数,你每次需要维护这个函数的a和b。所以只需要对两颗树状数组进行操作,每次更新整段区间的值即可。

赛后队友YY了一下这题为何是简单题。。当P点已经排好序的情况下,其实可以只维护两个前缀和,每次到达相应的P点,就更新该P点所拥有的函数的a和b,直接打印即可。。。

时间复杂度均为O(nlogn)

/*
@resources: GDCPC 2017 C
@date: 2017-05-08
@author: QuanQqqqq
@algorithm: 树状数组 
*/
#include <bits/stdc++.h>

#define ll long long
#define MAXN 1000005
#define lowbit(i) i & (-i)

using namespace std;

struct line{
    ll a,b; 
};

struct node{
    ll c,p,k;
    char ch[10];
}num[MAXN];

ll bits[2][MAXN];
ll pt[MAXN];

void add(ll i,ll v,ll p){
    while(i < MAXN){
        bits[p][i] += v;
        i += lowbit(i);
    }
}

ll query(ll i,ll p){
    ll ans = 0;
    while(i){
        ans += bits[p][i];
        i -= lowbit(i);
    }
    return ans;
}

int main(){
    int T;
    ll a,b,n;
    scanf("%d",&T);
    while(T--){
        scanf("%lld",&n);
        getchar();
        ll t = 0;
        memset(bits,0,sizeof(bits));
        for(ll i = 0;i < n;i++){
            scanf("%s %lld %lld %lld",num[i].ch,&num[i].c,&num[i].p,&num[i].k);
            getchar();
            pt[++t] = num[i].p;
        }
        pt[++t] = 0;
        sort(pt + 1,pt + t + 1);
        ll l = 1;
        for(ll i = 2;i <= t;i++){
            if(pt[i] != pt[l]){
                pt[++l] = pt[i];
            }
        }
        for(ll i = 0;i < n;i++){
            ll tmp = lower_bound(pt + 1,pt + 1 + l,num[i].p) - pt;
            if(num[i].ch[0] == 'C'){
                b = -num[i].p * num[i].k - num[i].c;
                add(tmp + 1,b,0);
                add(tmp + 1,num[i].k,1); 
                add(1,-num[i].c,0);
                add(tmp + 1,num[i].c,0);
            } else {
                b = num[i].p * num[i].k - num[i].c;
                add(tmp + 1,-b,0);
                add(1,b,0);
                add(tmp + 1,num[i].k,1);
                add(1,-num[i].k,1);
                add(tmp + 1,-num[i].c,0);
            }
        }
        for(ll i = 2;i <= l;i++){
            a = query(i,1);
            b = query(i,0);
            if(a == 0){
                printf("[%lld,%lld] b=%lld\n",pt[i - 1],pt[i],b);
            } else {
                if(b < 0){
                    printf("[%lld,%lld] b=%lld*x%lld\n",pt[i - 1],pt[i],a,b);
                } else {
                    printf("[%lld,%lld] b=%lld*x+%lld\n",pt[i - 1],pt[i],a,b);
                }
            }
        }
        a = query(MAXN,1);
        b = query(MAXN,0);
        if(a == 0){
            printf("[%lld,...] b=%lld*x+%lld\n",pt[l],a,b);
        } else {
            if(b < 0){
                printf("[%lld,...] b=%lld*x%lld\n",pt[l],a,b);
            } else {
                printf("[%lld,...] b=%lld*x+%lld\n",pt[l],a,b);
            }
        }
    }
}
/*
2
2
Call 20 30 10
Put 10 20 5
4
Call 32714 170443 16
Call 6846 101607 5
Call 1827 60167 31
Call 1909 124978 47
*/

Problem D:Boggle Game

题目大意:

还没读题,待补。。听说用来防AK的。。

算法思路:

//等待解题

Problem E: Dungeons & Dragons

题目大意:

有一个怪物有b滴血,你有两个方程分别是:
攻击时间:s + i * x
攻击伤害:w + i * y
i代表你的等级,vMax代表你的最高可到达的等级,s,w,x,y均为定值。
所有数据均不大于10^9次方

算法思路:

需要造成伤害血量=攻击次数*攻击伤害
有一个值一定是小于sqrt(b)的。所以只要枚举这两个值到sqrt(b)即可。
b最大为10^9所以,枚举到50000即可。
题目没有说攻击伤害会有0的情况。。

/*
@resources: GDCPC 2017 E
@date: 2017-5-8
@author: QuanQqqqq
@algorithm: 枚举 
*/
#include <bits/stdc++.h>

#define ll long long

using namespace std;

ll s,w,x,y,vMax,b;

ll getRankTime(ll i){
    ll time = (ll)ceil(b * 1.0 / (w + i * y));
    return time * (s + i * x);
}

ll getAttackTime(ll time){
    ll i = (ll)ceil((b * 1.0 / time - w) / y);
    return time * (s + i * x);
}

int main(){
    int T,cas = 1;
    scanf("%d",&T);
    while(T--){
        scanf("%lld %lld %lld %lld %lld %lld",&s,&w,&x,&y,&vMax,&b);
        ll ans = getRankTime(0);
        ll v = min(50000LL,vMax);
        for(ll i = 1;i <= v;i++){
            ans = min(ans,getRankTime(i));
        }
        for(ll i = 1;i <= 50000LL;i++){
            ans = min(ans,getAttackTime(i));
        }
        printf("Case #%d: %lld\n",cas++,ans);
    }
}
/*
2
2 2 2 2 8 10
2 2 1 2 8 10
*/

Problem F: Werewolves

题目大意:

有一大个屋子,现在需要知道这个屋子里有多少个房,且找出某一个房间到所有房间的距离(取所有距离的最大值),最小的房间。0为门或者路,1可以构成墙或者门的边边。
对于房间的门有以下定义:
门只能是2 * 5,2 * 4,4 * 2,5 * 2如下的格式
11 11 100001 1000001
00 00 100001 1000001
00 00
00 00
00 00
00 00
11
对于一个门,他有如下定义:
他旁边一定要有墙,且门两侧需要有路。对于每一个房间,必须要有拐角,即房间的长或者宽不能跟房间的长或者宽长得一样。

算法思路:

就。。一直dfs房间,dfs墙。。。。然后搞完之后再合并一下路径打出每个房间之间的路径,加一个floyd找最短路径的房间。。。很麻烦。。有空补。

//等待解题

Problem G: Scythe

题目大意:

给一棵树,需要你使得这棵树需要满足给定的最大深度和最小深度。

算法思路:

树形dp搞一搞。O(n^2)

//等待解题

Problem H: Codename

题目大意:

有n个女生和m个男生,每一个女生喜欢ai个男生,如果该男生被所有女生都喜欢,这个男生被叫做famous guys,现在问有多少个famous guys。

算法思路:

简单题,求最大覆盖,对于每一个女生喜欢ai个男生,那么她一定不喜欢m - ai个男生,这些不被喜欢的男生数肯定不是famous guy,再找找m个里有多少个是famous guy就可以了,注意判小于0的情况。

/*
@resources: GDCPC 2017 H
@date: 2017-05-09
@author: QuanQqqqq
@algorithm: yy
*/
#include <bits/stdc++.h>

#define ll long long
#define MAXN 2000005

using namespace std;

int main(){
    int T,cas = 1;
    scanf("%d",&T);
    ll n,m,tmp,ans;
    while(T--){
        scanf("%lld %lld",&n,&m);
        ans = m;
        for(ll i = 0;i < n;i++){
            scanf("%lld",&tmp);
            ans -= (m - tmp);
        }
        if(ans < 0){
            ans = 0;
        }
        printf("Case #%d: %lld\n",cas++,ans);
    }
}

Problem I: Betrayal at House on the Hill

题目大意:

给n个坐标,现在问这要使得这n个点都联通需要多长路径

算法思路:

最小生成树搞一发,详情请看红书P168页。
改改板样例过了。。

/*
@resources: GDCPC 2017 I
@date: 2017-05-10
@author: QuanQqqqq
@algorithm: yy
*/
#include <bits/stdc++.h>

using namespace std;

const int MAXN = 111111;
const int INF = 0x3f3f3f3f;

inline int lowbit(const int &x){
    return x & (-x);
}

struct Edge{
    int u,v;
    double c;
    Edge(int _u,int _v,double _c) : u(_u),v(_v),c(_c){}
    Edge(){}
}edge[MAXN * 4];

inline bool operator < (const Edge &a,const Edge &b){
    return a.c < b.c;
}

struct Node{
    int key,id;
    Node(int _k = 0,int _i = 0) : key(_k),id(_i){}
}Tree[MAXN];

inline bool operator < (const Node &a,const Node &b){
    return a.key < b.key;
}

int IDx[MAXN],IDy[MAXN],bak[MAXN];
int id[MAXN],father[MAXN],x[MAXN],y[MAXN];

int find(const int &x){
    return father[x] == x ? x : father[x] = find(father[x]);
}

inline bool cmp1(const int &i,const int &j){
    return x[i] - y[i] > x[j] - y[j] || x[i] - y[i] == x[j] - y[j] && y[i] > y[j]; 
}

inline bool cmp2(const int &i,const int &j){
    return x[i] - y[i] < x[j] - y[j] || x[i] - y[i] == x[j] - y[j] && y[i] > y[j];
}

inline bool cmp3(const int &i,const int &j){
    return x[i] + y[i] < x[j] + y[j] || x[i] + y[i] == x[j] + y[j] && y[i] > y[j];
}

inline bool cmp4(const int &i,const int &j){
    return x[i] + y[i] < x[j] < y[j] || x[i] + y[i] == x[j] + y[j] && y[i] < y[j]; 
}

inline void Process(int x[],int idx[],int n){
    for(int i = 0;i < n;i++){
        bak[i] = x[i];
    }
    sort(bak,bak + n,greater<int>());
    int p = unique(bak,bak + n) - bak;
    for(int i = 0;i < n;i++){
        idx[i] = lower_bound(bak,bak + p,x[i],greater<int>()) - bak + 1;
    }
}

inline void add_edge(int &N,const int &u,const int &v){
    edge[N++] = Edge(u,v,sqrt(pow(x[u] - x[v],2) + pow(y[u] - y[v],2)));
}

inline int get_min(const int &p){
    Node tmp(INF);
    for(int i = p;i;i ^= lowbit(i)){
        if(Tree[i].id != -1){
            tmp = min(tmp,Tree[i]);
        }
    }   
    return tmp.key == INF ? -1 : tmp.id;
}

inline void insert(const int &n,const int &p,const Node &it){
    for(int i = p;i <= n;i += lowbit(i)){
        if(Tree[i].id == -1 || it < Tree[i]){
            Tree[i] = it;
        }
    }   
}

inline double MinimumManhattanSpaningTree(int x[],int y[],int n){
    Process(x,IDx,n);
    Process(y,IDy,n);
    int N = 0;
    for(int i = 0;i < n;++i){
        id[i] = i;
    }
    sort(id,id + n,cmp1);
    for(int i = 1;i <= n;++i){
        Tree[i].id = -1;
    }
    for(int i = 0;i < n;++i){
        int u = id[i],v = get_min(IDy[u]);
        if(v != -1){
            add_edge(N,u,v); 
        }
        insert(n,IDy[u],Node(x[u] + y[u],u));
    }
    for(int i = 0;i < n;++i){
        id[i] = i;
    }
    sort(id,id + n,cmp2);
    for(int i = 1;i <= n;++i){
        Tree[i].id = -1;
    }
    for(int i = 0;i < n;++i){
        int u = id[i],v = get_min(IDx[u]);
        if(v != -1){
            add_edge(N,u,v);
        }
        insert(n,IDx[u],Node(x[u] + y[u],u));
    }
    for(int i = 0;i < n;++i){
        id[i] = i;
    }
    sort(id,id + n,cmp3);
    for(int i = 1;i <= n;++i){
        Tree[i].id = -1;
    }
    for(int i = 0;i < n;++i){
        int u = id[i],v = get_min(IDy[u]);
        if(v != -1){
            add_edge(N,u,v);
        }
        insert(n,IDy[u],Node(-x[u] + y[u],u));
    }
    for(int i = 0;i < n;++i){
        id[i] = i;
    }
    for(int i = 1;i <= n;++i){
        Tree[i].id = -1;
    }
    for(int i = 0;i < n;++i){
        int u = id[i],v = get_min(IDx[u]);
        if(v != -1){
            add_edge(N,u,v);
        }
        insert(n,IDx[u],Node(x[u] - y[u],u));
    }
    sort(edge,edge + N);
    for(int i = 0;i < n;++i){
        father[i] = i;
    }
    double res = 0;
    for(int i = 0;i < N;++i){
        int u = find(edge[i].u), v = find(edge[i].v);
        if(u != v){
            father[u] = v;
            res += edge[i].c;
        }
    }
    return res;
}

int main(){
    int T,cas = 1,n;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i = 0;i < n;i++){
            scanf("%d %d",&x[i],&y[i]);
        }
        printf("Case #%d: %.2lf\n",cas++,MinimumManhattanSpaningTree(x,y,n));
    }
}

/*
1
4
0 0
0 1
1 0
2 2
*/

Problem J: Carcassonne 

题目大意:

先有a(0,0),b1(1,0)这两个点,先a绕着b1旋转转出b2,然后a绕着b2转转出b2….一直旋转下去。。
然后从a点出发,跟着线走,现在问第n个点的坐标在哪里

算法思路:

比赛后期读的题,2分钟想到大概思路。。结果卡住了。。
对于一个n点,每次先找到比他大的2^k最小值,那么他一定绕着2^(k - 1)旋转,把这个点保存下来
然后位置回溯到n1 = 2^k - n
然后n1也继续找一个2^k1比他大的最小值。。。一直循环下去
直到ni为2^k结束,然后用这个ni这个点开始转回去。
由于这个点是第2^k个点,打一个40不到的表即可满足题目10^18的n这个数据。
然后需要一个旋转公式搞一搞。。

/*
@resources: GDCPC 2017 J
@date: 2017-5-8
@author: QuanQqqqq
@algorithm: yy
*/
#include <bits/stdc++.h>

#define ll long long
#define MAXN 100

using namespace std;

struct point{
    ll x,y;
    point(ll _x,ll _y) : x(_x),y(_y){}
    point(){}
};

point p[MAXN];
vector<ll> vs;

point xuanzhuan(point a,point b){
    point ans;
    ans.x = b.x + a.y - b.y;
    ans.y = b.x - a.x + b.y;
    return ans;
}

ll find(ll n){
    ll ans = 1;
    while(ans < n){
        ans <<= 1LL;
    }
    return ans;
}

bool check(ll n){
    ll total = 0;
    while(n){
        if(n & 1){
            total++;
        }
        n >>= 1;
    }
    return total <= 1;
}

ll getLen(ll n){
    ll ans = 0;
    while(n){
        n >>= 1;
        ans++;
    }
    return ans;
}

void init(){
    p[0] = point(0,0);
    p[1] = point(1,0);
    for(ll i = 2;i < MAXN;i++){
        p[i] = xuanzhuan(point(0,0),p[i - 1]);
    }
}

point getAns(ll n){
    point ans = p[getLen(n)];
    ll len = vs.size();
    for(ll i = len - 1;i >= 0;i--){
        ans = xuanzhuan(ans,p[vs[i]]);
    }
    vs.clear();
    return ans;
}

int main(){
    int T,cas = 1;
    ll n;
    point ans;
    scanf("%d",&T);
    while(T--){
        init();
        scanf("%lld",&n);
        while(n){
            ll t = find(n) - n;
            if(t == 0){
                ans = getAns(n);
                break;
            } else {
                vs.push_back(getLen(find(n) / 2));
                n = find(n) - n;
            }
        }
        printf("Case #%d: (%lld,%lld)\n",cas++,ans.x,ans.y);
    }
}

Problem K:Coup

题目大意:

还没读题,待补。。

算法思路:

//等待解题

Problem L:Advertising

题目大意:

一个XML需要渲染,对于每一个url,他有n条链接
可以是一个id链接到另一个url,或者一个id结束。
现在题目需要你从第一个url开始遍历,找出所有inline的id
可以重复打印。。忘记有没有回环了。。(题目并没有讲)

算法思路:

用一个map加一个vector存路径当邻接表,然后dfs遍历一次有向图,遇到inline的就输出就可以了。

/*
@resources: GDCPC 2017 L
@date: 2017-5-8
@author: QuanQqqqq
@algorithm: dfs
*/
#include <bits/stdc++.h>

#define ll long long
#define MAXN 3005

using namespace std;

map<string,vector<string> >mapp;
string root[MAXN];
map<string,bool> mapb;
bool flag;

void dfs(string str){
    if(mapb[str]){
        if(flag){
            cout << " ";
        }
        flag = true;
        cout << str;
        return ;
    }
    int len = mapp[str].size();
    for(int i = 0;i < len;i++){
        dfs(mapp[str][i]);
    }
}

int main(){
    int T,cas = 1;
    int n,t;
    string str1,str2,str3;
    scanf("%d",&T);
    while(T--){
        cin >> n;
        getchar();
        flag = false;
        mapb.clear();
        mapp.clear();
        for(int i = 0;i < n;i++){
            cin >> root[i] >> t;
            getchar();
            for(int j = 0;j < t;j++){
                cin >> str1 >> str2;
                if(str2 == "inline"){
                    mapb[str1] = true;
                    mapp[root[i]].push_back(str1);
                } else {
                    cin >> str3;
                    mapp[root[i]].push_back(str3);
                }
            }
        }
        printf("Case #%d: ",cas++);
        dfs(root[0]);
        cout << endl;
    } 
}
/*
2
2
http://demo.ad.com/vast1 2
id1 wrapper http://demo.ad.com/vast2
id2 inline
http://demo.ad.com/vast2 1
id3 inline
4
http://demo.ad.com/vast1 2
id1 wrapper http://demo.ad.com/vast2
id2 wrapper http://demo.ad.com/vast3
http://demo.ad.com/vast2 1
id3 wrapper http://demo.ad.com/vast4
http://demo.ad.com/vast3 2
id4 inline
id5 inline
http://demo.ad.com/vast4 1
id6 inline
*/
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值