Codeforces Round #101 (Div. 2)

C.Queue() 

TimeLimit:2000MSMemoryLimit:262144KB 
64bitIOFormat:%I64d|%I64u 

Description 

In the Main Berland Bank n  people stand in a queue at the cashier, everyone knows his/her height h i  , and the heights of the other people in the queue. Each of them keeps in mind number a i   — how many people who are taller than him/her and stand in queue in front of him.

After a while the cashier has a lunch break and the people in the queue seat on the chairs in the waiting room in a random order.

When the lunch break was over, it turned out that nobody can remember the exact order of the people in the queue, but everyone remembers his number a i   .

Your task is to restore the order in which the people stood in the queue if it is possible. There may be several acceptable orders, but you need to find any of them. Also, you need to print a possible set of numbers h i   — the heights of people in the queue, so that the numbers a i   are correct.

Input 

The first input line contains integer n  — the number of people in the queue (1n3000) . Then n  lines contain descriptions of the people as “name i   a i   ” (one description on one line), where name i   is a non-empty string consisting of lowercase Latin letters whose length does not exceed 10  characters (the i-th person’s name), a i   is an integer (0ain1)  , that represents the number of people who are higher and stand in the queue in front of person i  . It is guaranteed that all names are different.

Output 

If there’s no acceptable order of the people in the queue, print the single line containing “ 1  ” without the quotes. Otherwise, print in n  lines the people as “name i   h i   ”, where h i   is the integer from 1  to 109  (inclusive), the possible height of a man whose name is name i   . Print the people in the order in which they stand in the queue, starting from the head of the queue and moving to its tail. Numbers h i   are not necessarily unique.


SampleInput 
4
a 0
b 2
c 0
d 0
SampleOutput 
a 150
c 170
d 180
b 160

SampleInput 
4
vasya 0
petya 1
manya 3
dunay 3
SampleOutput 
-1


题意

给定 n  个人,并且给出某个人前方有多少个比他高的人的个数,求出他们的排列方式和每一个的高度,只要找出一种即可,如果找不出就输出1 .

解题思路

方法1:

针对找不出一种的情况:

  1. 先对给定的 n  个人进行排序,然后我们可以看出,如果当前某个人的前方人的个数r i  比他自身所带的有多少个比他打的人的个数 x i   要小,则一定不满足条件,输出 1  .

针对能够找出的情况:

  1. 我们将对每一个人分配 1>n  的高度,从个数 x i   高的开始处理,我们可以得知当前这个人能够得到的高度的最高值为 nx i   ,如果此数被占用了,就往下取就可以了,这样我们就能保证第 i  位前面有且仅有x i  个数比它大.

代码

时间复杂度: O(NK)  [  其中K 的值被输入数据影响,但复杂度肯定比 O(N 2 )  ] 

/*头文件模板*/

#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <vector>
#include <cctype>
#include <cstdio>
#include <string>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iomanip>
#include <typeinfo>
#include <iostream>
#include <algorithm>
#include <functional>

using namespace std;

#define pb push_back
#define mp make_pair
#define mem(a, x) memset(a, x, sizeof(a))
#define copy(a, b) memcpy(a, b, sizeof(a))
#define lson rt << 1, l, mid
#define rson rt << 1|1, mid + 1, r
#define FIN freopen("input.txt", "r", stdin)
#define FOUT freopen("output.txt", "w", stdout)

typedef long long LL;
typedef pair<int, int > PII;
typedef pair<int, string> PIS;
typedef pair<LL, LL>PLL;
typedef unsigned long long uLL;

template<typename T>
void print (T* p, T* q, string Gap = " ", bool flag = false) {
    int d = p < q ? 1 : -1;
    while (p != q) {
        if (flag) cout << Gap[0] << *p << Gap[1];
        else cout << *p;
        p += d;
        if (p != q && !flag) cout << Gap;
    }
    cout << endl;
}

template<typename T>
void print (const T &a, string bes = "") {
    int len = bes.length();
    if (len >= 2) cout << bes[0] << a << bes[1] << endl;
    else cout << a << endl;
}

template<typename T>
void debug (T* p, T* q, string Gap = " ", bool flag = false) {
#ifndef ONLINE_JUDGE
    int d = p < q ? 1 : -1;
    cout << "Debug out : ";
    while (p != q) {
        if (flag) cout << Gap[0] << *p << Gap[1];
        else cout << *p;
        p += d;
        if (p != q && !flag) cout << Gap;
    }
    cout << endl;
#endif
}

template<typename T>
void debug (const T &a, string bes = "") {
#ifndef ONLINE_JUDGE
    int len = bes.length();
    cout << "Debug out : ";
    if (len >= 2) cout << bes[0] << a << bes[1] << endl;
    else cout << a << endl;
#endif
}

void IO_Init() {
    ios::sync_with_stdio (false);
}

LL LLabs (const LL a) {
    return a >= 0 ? a : -a;
}

const double PI = 3.1415926535898;
const double eps = 1e-10;
const int MAXM = 1e5 + 5;
const int MAXN = 3e3 + 5;
const int INF = 0x3f3f3f3f;

/*头文件模板*/
struct o {
    string name;
    int h;
    o() {}
    o(string name, int h):name(name), h(h) {}
    bool operator < (const o & a) const {
        return h < a.h;
    }
};
o O[MAXN];
char S[MAXN];
bool visdp[MAXN];
int h[MAXN], n;
int main() {
#ifndef ONLINE_JUDGE
    //FIN;
    //FOUT;
#endif
    IO_Init();
    while(~scanf("%d", &n)) {
        int x;
        for(int i = 0; i < n; i ++) {
            scanf("%s%d", S, &x);
            O[i].name = string(S);
            O[i].h = x;
        }
        mem(visdp, false);
        sort(O, O + n);
        bool flag = true;
        for(int i = 0; i < n; i ++) {
            if(O[i].h > i) {
                flag = false;
                break;
            }
        }
        for(int i = n - 1; i >= 0; i --) {
            int k = n - O[i].h;
            while(visdp[k]) k --;
            visdp[h[i] = k] = true;
        }
        if(!flag) {
            puts("-1\n");
            continue;
        }
        for(int i = 0; i < n; i ++) {
            cout << O[i].name << ' ' << h[i] << endl;
        }
    }
    return 0;
}

方法2(codeforces 官方题解 ) 
针对找不出一种的情况:

  1. 先对给定的n 个人进行排序,然后我们可以看出,如果当前某个人的前方人的个数 r i   比他自身所带的有多少个比他打的人的个数 x i   要小,则一定不满足条件,输出 1  .

    针对能够找出的情况:

    1. 循环遍历从 0>n  ,然后res.insert(res.begin() + O[i].h, o(O[i].name, O[i].h))即可.

    代码

    时间复杂度: O(NK)  [  其中K 的值被输入数据影响,但复杂度肯定比 O(N 2 )  ] 

    /*头文件模板*/
    
    #include <map>
    #include <set>
    #include <cmath>
    #include <ctime>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <cctype>
    #include <cstdio>
    #include <string>
    #include <cstring>
    #include <sstream>
    #include <cstdlib>
    #include <iomanip>
    #include <typeinfo>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    
    using namespace std;
    
    #define pb push_back
    #define mp make_pair
    #define mem(a, x) memset(a, x, sizeof(a))
    #define copy(a, b) memcpy(a, b, sizeof(a))
    #define lson rt << 1, l, mid
    #define rson rt << 1|1, mid + 1, r
    #define FIN freopen("input.txt", "r", stdin)
    #define FOUT freopen("output.txt", "w", stdout)
    
    typedef long long LL;
    typedef pair<int, int > PII;
    typedef pair<int, string> PIS;
    typedef pair<LL, LL>PLL;
    typedef unsigned long long uLL;
    
    template<typename T>
    void print (T* p, T* q, string Gap = " ", bool flag = false) {
        int d = p < q ? 1 : -1;
        while (p != q) {
            if (flag) cout << Gap[0] << *p << Gap[1];
            else cout << *p;
            p += d;
            if (p != q && !flag) cout << Gap;
        }
        cout << endl;
    }
    
    template<typename T>
    void print (const T &a, string bes = "") {
        int len = bes.length();
        if (len >= 2) cout << bes[0] << a << bes[1] << endl;
        else cout << a << endl;
    }
    
    template<typename T>
    void debug (T* p, T* q, string Gap = " ", bool flag = false) {
    #ifndef ONLINE_JUDGE
        int d = p < q ? 1 : -1;
        cout << "Debug out : ";
        while (p != q) {
            if (flag) cout << Gap[0] << *p << Gap[1];
            else cout << *p;
            p += d;
            if (p != q && !flag) cout << Gap;
        }
        cout << endl;
    #endif
    }
    
    template<typename T>
    void debug (const T &a, string bes = "") {
    #ifndef ONLINE_JUDGE
        int len = bes.length();
        cout << "Debug out : ";
        if (len >= 2) cout << bes[0] << a << bes[1] << endl;
        else cout << a << endl;
    #endif
    }
    
    void IO_Init() {
        ios::sync_with_stdio (false);
    }
    
    LL LLabs (const LL a) {
        return a >= 0 ? a : -a;
    }
    
    const double PI = 3.1415926535898;
    const double eps = 1e-10;
    const int MAXM = 1e5 + 5;
    const int MAXN = 3e3 + 5;
    const int INF = 0x3f3f3f3f;
    
    /*头文件模板*/
    struct o {
        string name;
        int h;
        o() {}
        o(string name, int h):name(name), h(h) {}
        bool operator < (const o & a) const {
            return h < a.h;
        }
    };
    o O[MAXN];
    char S[MAXN];
    bool visdp[MAXN];
    int n;
    vector<o>res;
    int main() {
    #ifndef ONLINE_JUDGE
        //FIN;
        //FOUT;
    #endif
        IO_Init();
        while(~scanf("%d", &n)) {
            int x;
            for(int i = 0; i < n; i ++) {
                scanf("%s%d", S, &x);
                O[i].name = string(S);
                O[i].h = x;
            }
            res.clear();
            mem(visdp, false);
            sort(O, O + n);
            bool flag = true;
            for(int i = 0; i < n; i ++) {
                if(O[i].h > i) {
                    flag = false;
                    break;
                }
            }
            if(!flag) {
                puts("-1\n");
                continue;
            }
            for(int i = 0; i < n; i ++) {
                res.insert(res.begin() + O[i].h, o(O[i].name, n - i));
            }
    
            for(int i = 0; i < n; i ++) {
                cout << res[i].name << ' ' << res[i].h << endl;
            }
        }
        return 0;
    }
    

    D.TakeoffRamps() 

    Vasya participates in a ski race along the X  axis. The start is at point 0 , and the finish is at L  , that is, at a distance L  meters from the start in the positive direction of the axis. Vasya has been training so hard that he can run one meter in exactly one second.

    Besides, there are n  take-off ramps on the track, each ramp is characterized by four numbers:

    x i   represents the ramp’s coordinate

    d i   represents from how many meters Vasya will land if he goes down this ramp

    t i   represents the flight time in seconds

    p i   is the number, indicating for how many meters Vasya should gather speed to get ready and fly off the ramp. As Vasya gathers speed, he should ski on the snow (that is, he should not be flying), but his speed still equals one meter per second.

    Vasya is allowed to move in any direction on the X  axis, but he is prohibited to cross the start line, that is go to the negative semiaxis. Vasya himself chooses which take-off ramps he will use and in what order, that is, he is not obliged to take off from all the ramps he encounters. Specifically, Vasya can skip the ramp. It is guaranteed that x i +d i L , that is, Vasya cannot cross the finish line in flight.

    Vasya can jump from the ramp only in the positive direction of X  axis. More formally, when using the i -th ramp, Vasya starts gathering speed at point x i p i   , jumps at point x_i, and lands at point x i +d i   . He cannot use the ramp in opposite direction.

    Your task is to find the minimum time that Vasya will spend to cover the distance.

    Input

    The first line contains two integers n  and L(0n105,1L109) . Then n lines contain the descriptions of the ramps, each description is on a single line. Each description is a group of four non-negative integers x i ,d i ,t i ,p i (0x i L,1d i ,t i ,p i 109,x i +d i L)  .

    Output

    Print in the first line the minimum time in seconds Vasya needs to complete the track. Print in the second line k  — the number of take-off ramps that Vasya needs to use, and print on the third line of output k  numbers the number the take-off ramps Vasya used in the order in which he used them. Print each number exactly once, separate the numbers with a space. The ramps are numbered starting from 1  in the order in which they are given in the input.

    Examples

    input 
    2 20
    5 10 5 5
    4 16 1 7
    output 
    15
    1
    1
    input 
    2 20
    9 8 12 6
    15 5 1 1
    output 
    16
    1
    2

    Note 
    In the first sample, Vasya cannot use ramp 2  , because then he will need to gather speed starting from point 3 , which is not permitted by the statement. The optimal option is using ramp 1  , the resulting time is: moving to the point of gathering speed +  gathering speed until reaching the takeoff ramp +  flight time + moving to the finish line =0+5+5+5=15 .

    In the second sample using ramp 1  is not optimal for Vasya as t 1 >d 1  . The optimal option is using ramp 2  , the resulting time is: moving to the point of gathering speed +  gathering speed until reaching the takeoff ramp +  flight time +  moving to the finish line  =14+1+1+0=16  .

    题意

    有一个跑道,滑冰者从 0  开始滑冰到L ,中间给出了多个进行跳跃的部分,这些跳跃的部分有一定的缓冲区,从 x i p i   开始缓冲,到达 x i   处跳跃至 x i +d i   ,其中 x i +d i   这部分的时间花费为 t i   ,而不是跳跃部分则 1  秒钟1 米,最终求从 0  滑到L 最小花费多少时间?
    [  记住一点,这个人可以往回走,这个点被坑了,实在是无法理解出题的人拿这个点坑人,竟然还可以直接往回走,我服了,如果第10 组过不了,基本就是这个原因 ] 

    解题思路

    0,L,x i p i ,x i +d i   Hash  将进行离散化, Hash  的方法有若干种,我直接用的 map  ,然后将这些点看成一个有向图上的点,其中花费 t  则是点与点之间的有权值的边,如此便转换为求0  L  的最短路,时间复杂度基本就是求最短路的复杂度了.

    [ 这里我们可以记住一个技巧,单独求解一个点到另一个点的最小最大花费可以转换为图进行处理,我想很多图论方面都可以用来处理相应的问题 ] 

    代码

    代码复杂度:O(E+VlogV) 

    /*头文件模板*/
    
    #include <map>
    #include <set>
    #include <cmath>
    #include <ctime>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <cctype>
    #include <cstdio>
    #include <string>
    #include <cstring>
    #include <sstream>
    #include <cstdlib>
    #include <iomanip>
    #include <typeinfo>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    
    using namespace std;
    
    #define pb push_back
    #define mp make_pair
    #define mem(a, x) memset(a, x, sizeof(a))
    #define copy(a, b) memcpy(a, b, sizeof(a))
    #define lson rt << 1, l, mid
    #define rson rt << 1|1, mid + 1, r
    #define FIN freopen("input.txt", "r", stdin)
    #define FOUT freopen("output.txt", "w", stdout)
    
    typedef long long LL;
    typedef pair<int, int > PII;
    typedef pair<int, string> PIS;
    typedef pair<LL, LL>PLL;
    typedef pair<LL, int>PLI;
    typedef unsigned long long uLL;
    
    template<typename T>
    void print (T* p, T* q, string Gap = " ", bool flag = false) {
        int d = p < q ? 1 : -1;
        while (p != q) {
            if (flag) cout << Gap[0] << *p << Gap[1];
            else cout << *p;
            p += d;
            if (p != q && !flag) cout << Gap;
        }
        cout << endl;
    }
    
    template<typename T>
    void print (const T &a, string bes = "") {
        int len = bes.length();
        if (len >= 2) cout << bes[0] << a << bes[1] << endl;
        else cout << a << endl;
    }
    
    template<typename T>
    void debug (T* p, T* q, string Gap = " ", bool flag = false) {
    #ifndef ONLINE_JUDGE
        int d = p < q ? 1 : -1;
        cout << "Debug out : ";
        while (p != q) {
            if (flag) cout << Gap[0] << *p << Gap[1];
            else cout << *p;
            p += d;
            if (p != q && !flag) cout << Gap;
        }
        cout << endl;
    #endif
    }
    
    template<typename T>
    void debug (const T &a, string bes = "") {
    #ifndef ONLINE_JUDGE
        int len = bes.length();
        cout << "Debug out : ";
        if (len >= 2) cout << bes[0] << a << bes[1] << endl;
        else cout << a << endl;
    #endif
    }
    
    void IO_Init() {
        ios::sync_with_stdio (false);
    }
    
    LL LLabs (const LL a) {
        return a >= 0 ? a : -a;
    }
    
    const double PI = 3.1415926535898;
    const double eps = 1e-10;
    const int MAXM = 1e5 + 5;
    const int MAXN = 2e5 + 5;
    const LL INF = 1e18;
    
    /*头文件模板*/
    
    struct o {
        LL x, d, t, p;
    } R[MAXN];
    struct Edge {
        int to, id;
        LL cost;
        bool operator < (const Edge & a) const {
            return cost < a.cost;
        }
        Edge() {}
        Edge(int to, LL cost, int id): to(to), cost(cost), id(id) {}
    };
    map<LL, int>DI;
    vector<Edge>G[MAXN];
    LL d[MAXN], L;
    int n;
    PII prev[MAXN];
    stack<int>S;
    void init() {
        DI.clear();
        for(int i = 0; i < MAXN; i ++) {
            G[i].clear();
            prev[i].first = i;
            prev[i].second = -1;
        }
    }
    
    void dijkstra() {
    
        priority_queue<PLI, vector<PLI>, greater<PLI> >que;
        fill(d, d + MAXN, INF);
        d[DI[0]] = 0;
        que.push(PII(0, 1));
        while(!que.empty()) {
            PLI p = que.top();
            que.pop();
            int v = p.second;
            if(d[v] < p.first) continue;
            for(int i = 0; i < G[v].size(); i ++) {
                Edge &e = G[v][i];
                if(d[e.to] > d[v] + e.cost) {
                    d[e.to] = d[v] + e.cost;
                    prev[e.to].first = v;
                    prev[e.to].second = e.id;
                    que.push(PII(d[e.to], e.to));
                }
            }
        }
    
        printf("%lld\n", d[DI[L]]);
    
        while(!S.empty()) S.pop();
    
        for(int t = DI[L]; t != prev[t].first; t = prev[t].first) {
            if(prev[t].second != -1) {
                S.push(prev[t].second);
            }
        }
        printf("%d\n", S.size());
        while(!S.empty()) {
            printf("%d", S.top());
            S.pop();
            if(S.empty()) {
                printf("\n");
            } else {
                printf(" ");
            }
        }
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        //FIN;
        //FOUT;
    #endif
        IO_Init();
    
        while(~scanf("%d%lld", &n, &L)) {
            init();
            DI[0] = 1;
            DI[L] = 1;
            for(int i = 0; i < n; i ++) {
                scanf("%lld%lld%lld%lld", &R[i].x, &R[i].d, &R[i].t, &R[i].p);
                if(R[i].x - R[i].p < 0 || R[i].x + R[i].d > L || R[i].t > R[i].p + R[i].d) continue;
                DI[R[i].x - R[i].p] = 1;
                DI[R[i].x + R[i].d] = 1;
            }
            int ib = 1;
            for(map<LL, int>::iterator it = DI.begin(), itt = DI.begin(); it != DI.end(); it ++) {
                if(ib > 1) {
                    G[ib - 1].pb(Edge(ib, it -> first - itt -> first, -1));
                    G[ib].pb(Edge(ib - 1, it -> first - itt -> first, -1));
                    itt ++;
                }
                it -> second = ib ++;
            }
            for(int i = 0; i < n; i ++) {
                if(R[i].x - R[i].p < 0 || R[i].x + R[i].d > L || R[i].t > R[i].p + R[i].d) continue;
                int u = DI[R[i].x - R[i].p];
                int v = DI[R[i].x + R[i].d];
                G[u].pb(Edge(v, R[i].p + R[i].t, i + 1));
            }
            dijkstra();
        }
        return 0;
    }
    

    E.ClearingUp() 

    TimeLimit:2000MSMemoryLimit:262144KB 
    64bitIOFormat:%I64d|%I64u 

    Description 

    After Santa Claus and his assistant Elf delivered all the presents and made all the wishes come true, they returned to the North Pole and found out that it is all covered with snow. Both of them were quite tired and they decided only to remove the snow from the roads connecting huts. The North Pole has n huts connected with m roads. One can go along the roads in both directions.

    The Elf offered to split: Santa Claus will clear up the wide roads and the Elf will tread out the narrow roads. For each road they decided who will clear it: Santa Claus or the Elf. To minimize the efforts they decided to clear the road so as to fulfill both those conditions:

    between any two huts should exist exactly one simple path along the cleared roads;
    Santa Claus and the Elf should clear the same number of roads.
    At this point Santa Claus and his assistant Elf wondered which roads should they clear up?

    input 

    The first input line contains two positive integers n and m (1n103,1m105)  — the number of huts and the number of roads. Then follow m lines, each of them contains a road description: the numbers of huts it connects — x  and y  (1x,yn)  and the person responsible for clearing out this road (  S ” — for the Elf or “ M  ” for Santa Claus) . It is possible to go on each road in both directions. Note that there can be more than one road between two huts and a road can begin and end in the same hut.

    Output 

    Print “ 1  ” without the quotes if it is impossible to choose the roads that will be cleared by the given rule. Otherwise print in the first line how many roads should be cleared and in the second line print the numbers of those roads (the roads are numbered from 1  in the order of occurrence in the input). It is allowed to print the numbers of the roads in any order. Each number should be printed exactly once. As you print the numbers, separate them with spaces.


    SampleInput 
    1 2
    1 1 S
    1 1 M
    SampleOutput 
    0

    SampleInput 
    3 3
    1 2 S
    1 3 M
    2 3 S
    SampleOutput 
    2
    2 1
    SampleInput 
    5 6
    1 1 S
    1 2 M
    1 3 S
    1 4 M
    1 5 M
    2 2 S

    SampleOutput 
    -1


    题意

    S  ,M 两个不同颜色标记的边,求得一个生成树,其中两种颜色的边各占一半.

    解题思路

    1. 如果当前构成生成树的顶点为 n  的话,如果n1 不是为偶数就输出 1  .

    2. 将当前的 S  这个颜色构成的边全部都删除,即不加入生成树中,记剩下的联通块为cnt ,如果 cnt1>(n1)2   ,输出 1  ,因为将所有的 S  边都加上都无法满足两种颜色各占一半.

    3. 2 的基础上,我们将连接这些联通块的边保存起来,因为这些边必须要存在的,如果这些边不够 (n1)2   ,则随意增加 k  条边满足条件.

    4. 3 的基础上,将剩下的 M  颜色的边加入,最后将生成树输出

    代码

    时间复杂度:O(NE) 

    /*头文件模板*/
    
    #include <map>
    #include <set>
    #include <cmath>
    #include <ctime>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <cctype>
    #include <cstdio>
    #include <string>
    #include <cstring>
    #include <sstream>
    #include <cstdlib>
    #include <iomanip>
    #include <typeinfo>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    
    using namespace std;
    
    #define pb push_back
    #define mp make_pair
    #define mem(a, x) memset(a, x, sizeof(a))
    #define copy(a, b) memcpy(a, b, sizeof(a))
    #define lson rt << 1, l, mid
    #define rson rt << 1|1, mid + 1, r
    #define FIN freopen("input.txt", "r", stdin)
    #define FOUT freopen("output.txt", "w", stdout)
    
    typedef long long LL;
    typedef pair<int, int > PII;
    typedef pair<int, string> PIS;
    typedef pair<LL, LL>PLL;
    typedef unsigned long long uLL;
    
    template<typename T>
    void print (T* p, T* q, string Gap = " ", bool flag = false) {
        int d = p < q ? 1 : -1;
        while (p != q) {
            if (flag) cout << Gap[0] << *p << Gap[1];
            else cout << *p;
            p += d;
            if (p != q && !flag) cout << Gap;
        }
        cout << endl;
    }
    
    template<typename T>
    void print (const T &a, string bes = "") {
        int len = bes.length();
        if (len >= 2) cout << bes[0] << a << bes[1] << endl;
        else cout << a << endl;
    }
    
    template<typename T>
    void debug (T* p, T* q, string Gap = " ", bool flag = false) {
    #ifndef ONLINE_JUDGE
        int d = p < q ? 1 : -1;
        cout << "Debug out : ";
        while (p != q) {
            if (flag) cout << Gap[0] << *p << Gap[1];
            else cout << *p;
            p += d;
            if (p != q && !flag) cout << Gap;
        }
        cout << endl;
    #endif
    }
    
    template<typename T>
    void debug (const T &a, string bes = "") {
    #ifndef ONLINE_JUDGE
        int len = bes.length();
        cout << "Debug out : ";
        if (len >= 2) cout << bes[0] << a << bes[1] << endl;
        else cout << a << endl;
    #endif
    }
    
    void IO_Init() {
        ios::sync_with_stdio (false);
    }
    
    LL LLabs (const LL a) {
        return a >= 0 ? a : -a;
    }
    
    const double PI = 3.1415926535898;
    const double eps = 1e-10;
    const int MAXM = 1e5 + 5;
    const int MAXN = 1e3 + 5;
    const int INF = 0x3f3f3f3f;
    
    /*头文件模板*/
    
    struct Edge {
        int x, y, b;
        Edge() {}
        Edge(int x, int y, int b = -1): x(x), y(y), b(b) {}
    };
    
    int n, m;
    int par[MAXN], ranks[MAXN];
    vector<Edge> S, W;//保存提供的边
    vector<PII> TS, TW;//保存最后会留在生成树中边
    void BC_init() {
        for(int i = 0; i < MAXN; i ++) {
            par[i] = i;
            ranks[i] = 0;
        }
    }
    
    int find(int x) {
        return par[x] == x ? x : par[x] = find(par[x]);
    }
    
    bool merge(int x, int y) {
        x = find(x);
        y = find(y);
        if(x == y) return false;
        if(ranks[x] < ranks[y]) {
            par[x] = y;
        } else {
            par[y] = x;
            if(ranks[x] == ranks[y]) {
                ranks[x] ++;
            }
        }
        return true;
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        //FIN;
        //FOUT;
    #endif
        IO_Init();
        while(~scanf("%d%d", &n, &m)) {
    
    
            int x, y;
            char who[2];
            S.clear(), W.clear();
            TS.clear(), TW.clear();
    
    
            for(int i = 0; i < m; i ++) {
                scanf("%d%d%s", &x, &y, who);
                if(who[0] == 'S') S.push_back(Edge(x, y, i + 1));
                else W.push_back(Edge(x, y, i + 1));
            }
    
            //顶点数目为偶数,提供的边的数目不满足条件
            if(n % 2 == 0 || n - 1 > m) {
                puts("-1");
                continue;
            }
    
            //初始化并查集
            BC_init();
    
            //求解多少个联通块
            int ltk = n;
            for(int i = 0; i < W.size(); i ++) {
                if(merge(W[i].x, W[i].y)) {
                    ltk --;
                }
            }
            //如果不满足条件
            if(ltk - 1> (n - 1) >> 1) {
                puts("-1");
                continue;
            }
    
            //将连接这些联通块的边加入
            for(int i = 0; i <  S.size(); i ++) {
                if(merge(S[i].x, S[i].y)) {
                    TS.push_back(PII(i, S[i].b));
                }
            }
    
            BC_init();
    
            //重构生成树,加入必须要加入的边
            for(int i = 0;i <  TS.size();i ++){
                merge(S[TS[i].first].x, S[TS[i].first].y);
            }
            //凑足(n-1)/2条边
            int sn = TS.size();
            for(int i = 0;i < S.size();i ++){
                if(sn == (n - 1) >> 1) break;
                if(merge(S[i].x, S[i].y)){
                    sn ++;
                    TS.push_back(PII(i, S[i].b));
                }
            }
    
            if(sn < (n - 1) >> 1){
                puts("-1");
                continue;
            }
    
            //凑足另外一条边
            int wn = 0;
            for(int i = 0;i < W.size();i ++){
                if(wn == (n - 1) >> 1) break;
                if(merge(W[i].x, W[i].y)){
                    TW.push_back(PII(i, W[i].b));
                    wn ++;
                }
            }
    
            if(wn < (n - 1) >> 1){
                puts("-1");
                break;
            }
    
    
            printf("%d\n", TW.size() + TS.size());
            for(int i = 0;i < TW.size();i ++){
                printf("%d", TW[i].second);
                if(i != TW.size() - 1) printf(" ");
            }
    
    
            for(int i = 0;i <  TS.size();i ++){
                printf(" %d", TS[i].second);
            }
    
    
            printf("\n");
        }
        return 0;
    }

添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值