并查集

刷了好多题,来贴点题解嘻嘻嘻

普通并查集
Kruskal最小生成树
逆向并查集
带权并查集

牛客网_任意点

#include<bits/stdc++.h>
using namespace std;
int fa[2010], x[110], y[110], rem[1010];
void Init(){
    for(int i = 1; i <= 2000; i++) fa[i] = i;
}
int Find(int t){
    if(t != fa[t]) fa[t] = Find(fa[t]);
    return fa[t];
}
int main(){
    int n, ans = 0;
    cin >> n;
    Init();
    for(int i = 0; i < n; i++){
        cin >> x[i] >> y[i];
        y[i] += 1000;
        int fx = Find(x[i]), fy = Find(y[i]);
        fa[fy] = fx;
    }
    for(int i = 0; i < n; i++){
        int fx = Find(x[i]);
        ans += (rem[fx] == 0);
        rem[fx] = 1;
    }
    cout << ans - 1 << endl;
    return 0;
}

HDU1272_小希的迷宫

#include<bits/stdc++.h>
using namespace std;
static const int Maxn = 1e5 + 10;
int rem[Maxn], fa[Maxn], cnt;
bool flag;
void Init(){
    for(int i = 1; i <= Maxn; i++) fa[i] = i;
    memset(rem, 0, sizeof(rem));
    flag = true; cnt = 0;
}
bool ask(){
    if((!flag) || cnt > 1) return false;
    return true;
}
int Find(int x){
    if(x != fa[x]) fa[x] = Find(fa[x]);
    return fa[x];
} 
void query(int x, int y){
    cnt += 2 - rem[x] - rem[y];
    rem[x] = rem[y] = 1;
    int fx = Find(x), fy = Find(y);
    if(fx == fy) flag = false;
    else {fa[fx] = fy; cnt--;} 
}
int main(){
    int x, y;
    while(scanf("%d%d", &x, &y) && x != -1 && y != -1){
        if(x == 0 && y == 0){
            printf(ask() ? "Yes\n" : "No\n");
            Init(); continue;
        }
        if(flag) query(x, y);
    }
    return 0;
} 

HDU1233_还是畅通工程

#include<bits/stdc++.h>
using namespace std;
static const int Maxn = 110;
typedef struct{
    int u, v, w;
}D;
D d[Maxn * Maxn];
int fa[Maxn]; 
void Init(int n){
    for(int i = 1; i <= n; i++) fa[i] = i;
}
int Find(int x){
    if(x != fa[x]) fa[x] = Find(fa[x]);
    return fa[x]; 
}
bool cmp(D x, D y){
    return x.w < y.w;
}
int main()
{
    int n;
    while(scanf("%d", &n) && n != 0){
        Init(n);
        int len = n * (n - 1) / 2, sum = 0;
        for(int i = 0; i < len; i++) scanf("%d%d%d", &d[i].u, &d[i].v, &d[i].w);
        sort(d, d + len, cmp);//边权排序 
        for(int i = 0; i < len; i++){
            int fx = Find(d[i].u), fy = Find(d[i].v);
            if(fx != fy){
                fa[fx] = fy;
                sum += d[i].w;
            }
        }
        printf("%d\n", sum);
    }
    return 0;
}

HDU4496_D-City

#include<bits/stdc++.h>
using namespace std;
static const int Maxn = 1e4 + 10;
static const int Maxm = 1e5 + 10; 
typedef pair <int ,int> P;
P p[Maxm];
int ans[Maxm], fa[Maxn];
void Init(int N){
    for(int i = 0; i < N; i++) fa[i] = i;
}
int Find(int x){
    if(x != fa[x]) fa[x] = Find(fa[x]);
    return fa[x];
}
bool Query(int x, int y){
    int fx = Find(x), fy = Find(y);
    if(fx == fy) return false;
    fa[fx] = fy; return true;
}
void Print(int M){
    for(int i = 1; i <= M; i++) printf("%d\n", ans[i]);
}
int main(){
    int N, M;//又TM是多组数据 
    while(scanf("%d%d", &N, &M) != EOF){
        for(int i = 0; i < M; i++) scanf("%d%d", &p[i].first, &p[i].second);
        Init(N);
        ans[M] = N;
        for(int i = M - 1; i >= 0; i--){
            ans[i] = ans[i + 1];
            if(Query(p[i].first, p[i].second)) ans[i] --;
        }//如果加边的两点不属于一个块就ans-- 
        Print(M);
    }
    return 0;
}

Poj1182_食物链

#include<bits/stdc++.h>
using namespace std;
class DisjointSet{
private:
    int *fa, *r;
public:
    DisjointSet(int size){
        fa = new int[size];
        r = new int[size];
        for(int i = 1; i <= size; i++){
            fa[i] = i; r[i] = 0;//relation 0同类,1被fa吃,2吃fa 
        }
    }
    ~DisjointSet(){
        delete [] fa;
        delete [] r;
    } 
    int find_set(int node){
        if(node != fa[node]){
            int pre = fa[node];//!
            fa[node] = find_set(fa[node]);
            r[node] = (r[node] + r[pre]) % 3;
        }
        return fa[node];
    }
    int solve(int d, int x, int y){
        int fx = find_set(x), fy = find_set(y);
        if(fx == fy){
            if((r[y] - r[x] + 3) % 3 == d - 1) return 0;//!
            else return 1;
        }
        fa[fy] = fx;//!
        r[fy] = (r[x] - r[y] + d + 2) % 3;//!
        return 0;
    }
};
int main(){
    int N, K, ans = 0, d, x, y;
    cin >> N >> K;
    DisjointSet dsu(N);
    while(K--){
        cin >> d >> x >> y;
        if(x > N || y > N || (x == y && d == 2)) ans++;
        else ans += dsu.solve(d, x, y);
    }
    cout << ans << endl; 
    return 0;
}

Poj2492_A Bug's Life
C语言

#include<stdio.h>
int fa[2010], r[2010];
bool flag;
int Find(int node){
    if(node != fa[node]){
        int pre = fa[node];
        fa[node] = Find(fa[node]);
        r[node] = (r[node] + r[pre]) % 2;
    }
    return fa[node];
}
int main(){
    int T, n, k, kase = 0, x, y, fx, fy;
    scanf("%d", &T);
    while(T--){
        flag = true;
        scanf("%d%d", &n, &k);
        for(int i = 1; i <= n; i++){ fa[i] = i; r[i] = 0;} 
        while(k--){
            scanf("%d%d", &x, &y);
            if(!flag) continue; 
            fx = Find(x); fy = Find(y);
            if(fx != fy){
                fa[fy] = fx;
                r[fy] = (r[x] - r[y] + 1) % 2;
            }
            else if(r[x] == r[y]) flag = false;//这里不能加break!!!否则后面的输入操作就没了 
        }
        if(kase > 0) printf("\n");
        if(!flag) printf("Scenario #%d:\nSuspicious bugs found!\n", ++kase);
        else printf("Scenario #%d:\nNo suspicious bugs found!\n", ++kase);
    }
    return 0;
}

C++

#include<cstdio>
using namespace std;
class DisjointSet{
private:
    int *fa, *r;
public:
    DisjointSet(int size){
        fa = new int[size];
        r = new int[size];
    }
    ~DisjointSet(){
        delete [] fa;
        delete [] r;
    } 
    void Init(int size){
        for(int i = 1; i <= size; i++){
            fa[i] = i; r[i] = 0;
        }
    }
    int find_set(int node){
        if(node != fa[node]){
            int pre = fa[node];//!
            fa[node] = find_set(fa[node]);
            r[node] = (r[node] + r[pre]) % 2;
        }
        return fa[node];
    }
    bool solve(int x, int y){
        int fx = find_set(x), fy = find_set(y);
        if(fx == fy){
            if(r[x] == r[y]) return false;//!
            else return true;
        }
        fa[fy] = fx;//!
        r[fy] = (r[x] - r[y] + 1) % 2;//!
        return true;
    }
};
int main(){
    DisjointSet dsu(2010);
    int T, kase = 0, n, k, x, y;
    bool flag;
    scanf("%d", &T); 
    while(T--){
        scanf("%d%d", &n, &k);
        flag = true;
        dsu.Init(n);
        while(k--){
            scanf("%d%d", &x, &y);
            if(flag && !dsu.solve(x, y)) flag = false;//没有break没有beak没有beak 
        }
        if(kase > 0) printf("\n");
        if(!flag) printf("Scenario #%d:\nSuspicious bugs found!\n", ++kase);
        else printf("Scenario #%d:\nNo suspicious bugs found!\n", ++kase);
    }
    return 0;
}

Poj1984_Navigation Nightmare

#include<cstdio>
#include<map>
#include<algorithm>
using namespace std; 
static const int Maxn = 4e4 + 10;
static const int Maxm = 4e4 + 10;
static const int Maxk = 1e4 + 10; 
typedef struct{
    int x, y, t;
}Query;
Query q[Maxk];
map <char, int> dir;
int fa[Maxn], ew[Maxn], sn[Maxn], x[Maxm], y[Maxm], len[Maxm];
char d[Maxm][10];

void Init(int size){
    for(int i = 1; i <= size; i++) fa[i] = i;
    dir['E'] = dir['S'] = 1;
    dir['W'] = dir['N'] = -1;
}
int Find(int x){
    if(x != fa[x]){
        int pre = fa[x];
        fa[x] = Find(fa[x]);
        ew[x] += ew[pre]; sn[x] += sn[pre];
    }
    return fa[x];
}
void query(int x, int y){
    int fx = Find(x), fy = Find(y);
    if(fx != fy) printf("-1\n");
    else printf("%d\n", abs(ew[x] - ew[y]) + abs(sn[x] - sn[y]));
}
bool cmp(Query a, Query b){
    return a.t < b.t;
}
int main()
{
    int n, m, k, j = 1;
    scanf("%d%d", &n ,&m);
    Init(n);
    for(int i = 1; i <= m; i++) scanf("%d%d%d%s", &x[i], &y[i], &len[i], d[i]);
    scanf("%d", &k);
    for(int i = 1; i <= k; i++) scanf("%d%d%d", &q[i].x, &q[i].y, &q[i].t);
    sort(q, q + k, cmp);
    for(int i = 1; i <= m; i++){
        int fx = Find(x[i]), fy = Find(y[i]);
        if(d[i][0] == 'E' || d[i][0] == 'W'){
            fa[fy] = fx;
            ew[fy] = ew[x[i]] - ew[y[i]] + dir[d[i][0]] * len[i]; 
            sn[fy] = sn[x[i]] - sn[y[i]];
        }
        else{
            fa[fy] = fx;
            ew[fy] = ew[x[i]] - ew[y[i]]; 
            sn[fy] = sn[x[i]] - sn[y[i]] + dir[d[i][0]] * len[i];
        }
        while(j <= k && q[j].t == i){query(q[j].x, q[j].y); j++;} 
    }
    return 0;
}

Poj1988_Cube Stacking

#include<cstdio>
using namespace std;
static const int Maxn = 3e4 + 10; 
int fa[Maxn], V[Maxn], r[Maxn];
/*
V[i]表示i所在堆的数量 
r[i]表示i之下的块数 
*/
void Init(){
    for(int i = 1; i <= 3e4; i++){
        fa[i] = i; V[i] = 1; r[i] = 0;
    }
}
int Find(int x){
    if(x != fa[x]){
        int pre = fa[x];
        fa[x] = Find(fa[x]);
        V[x] = V[pre]; r[x] += r[pre];
    }
    return fa[x];
}
void Move(int x, int y){
    int fx = Find(x), fy = Find(y);
    fa[fx] = fy; r[fx] += V[fy]; V[fy] += V[fx];
}
void Count(int x){
    Find(x);//更新上一次操作 
    printf("%d\n", r[x]);
}
int main(){
    int P, x, y;
    char opr[10];
    scanf("%d", &P);
    Init();
    while(P--){
        scanf("%s%d", opr, &x);
        if(opr[0] == 'M'){
            scanf("%d", &y); Move(x, y);
        }
        else Count(x);
    }
    return 0;
}

HDU3635_Dragon Balls

#include<bits/stdc++.h>
using namespace std;
static const int Maxn = 1e4+10;
int fa[Maxn], cnt[Maxn], t[Maxn], kase;
void Init(int N){
    for(int i = 0; i <= N; i++){
        fa[i] = i; cnt[i] = 1; t[i] = 0;
    }
}
int Find(int x){
    if(x != fa[x]){
        int pre = fa[x];
        fa[x] = Find(fa[x]);
        cnt[x] = cnt[pre];
        t[x] += t[pre];
    }
    return fa[x];
}
void Trans(int x, int y){
    int fx = Find(x), fy = Find(y);
    fa[fx] = fy; 
    cnt[fy] += cnt[fx]; 
    t[fx]++;
} 
void Query(int x){
    Find(x);
    printf("%d %d %d\n", fa[x], cnt[x], t[x]);
}
int main()
{
    int T, N, k, x, y;
    char opr[10];
    scanf("%d", &T);
    while(T--){
        scanf("%d%d", &N, &k);
        Init(N);
        printf("Case %d:\n", ++kase);
        while(k--){
            scanf("%s%d", opr, &x);
            if(opr[0] == 'T'){
                scanf("%d", &y); Trans(x, y);
            }
            else Query(x);
        }
    }
    return 0;
} 

Poj1733_Parity game
自己打的vector

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
static const int Maxn = 5010;
typedef struct{
    int u, v, w;
}Node;
Node d[Maxn];
vector <int> Hash;//可以用数组 
int fa[Maxn * 2], r[Maxn * 2];
void init(int size){
    for(int i = 0; i <= size; i++) fa[i] = i;
}
int Find(int x){
    if(x != fa[x]){
        int pre = fa[x];
        fa[x] = Find(fa[x]); r[x] = r[x] ^ r[pre];
    }
    return fa[x];
}
bool query(int x, int y, int conf){
    int fx = Find(x), fy = Find(y);
    if(fx == fy){
        if(r[x]^r[y] == conf) return true;
        else return false;
    }
    if(fy < fx) swap(fy, fx);//这句话其实也可以不要 
    fa[fy] = fa[fx]; r[fy] = r[y] ^ conf ^ r[x];
    return true;
}
int main(){
    int n, k, x, y, ans = 0;
    char s[10];
    bool flag = true;
    scanf("%d%d", &n ,&k);
    for(int i = 0; i < k; i++){
        scanf("%d%d%s", &d[i].u, &d[i].v, s);
        d[i].w = (s[0] == 'e') ? 0 : 1;//奇偶处理 
        Hash.push_back(d[i].u - 1); //左闭右开,离散化 
        Hash.push_back(d[i].v);
    }
    sort(Hash.begin(), Hash.end());
    n = unique(Hash.begin(), Hash.end()) - Hash.begin();//去重 
    init(n);
    for(int i = 0; i < k && flag; i++){
        x = lower_bound(Hash.begin(), Hash.begin() + n, d[i].u - 1) - Hash.begin();
        y = lower_bound(Hash.begin(), Hash.begin() + n, d[i].v) - Hash.begin();
        if(!query(x, y, d[i].w)) flag = false;
        if(flag)ans++;
    }
    printf("%d", ans);
    return 0;
} 

用vector好傻 网上找的数组

#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 100005;
int fa[maxn], val[maxn], n, m;
int hashSet[maxn];
struct {
    int u, v, w;
}node[maxn];
int find(int n){
    int k = fa[n];
    if(fa[n] != n){
        fa[n] = find(fa[n]);
        val[n] = (val[n] + val[k])%2;
    }
    return fa[n];
}
void init(){
    for (int i = 0; i <= n; ++i)
        val[i] = 0, fa[i] = i;
}
int main(){
    while (~scanf("%d", &n)){
        //init放这儿会RE,想想为什么,其实也可以不炸。。 
        int i, k = 0;
        scanf("%d%d", &n, &m);
        for (i = 0; i < m; ++i){
            char s[5];
            scanf("%d%d%s", &node[i].u, &node[i].v, s);
            node[i].w = s[0] == 'e'? 0 : 1;
            hashSet[k++] = node[i].u - 1;
            hashSet[k++] = node[i].v;
        }
        sort(hashSet, hashSet+k);
        n = (int)(unique(hashSet, hashSet+k) - hashSet);
        init();
        for (i = 0; i < m; ++i){
            int u = (int)(lower_bound(hashSet, hashSet + n, node[i].u-1) - hashSet);
            int v = (int)(lower_bound(hashSet, hashSet + n, node[i].v) - hashSet);
            
            int fu = find(u), fv = find(v);
            
            if (fu == fv && (val[u] + node[i].w)%2 != val[v])
                break;
            if (fu < fv){
                fa[fv] = fu;
                val[fv] = (val[u] + node[i].w - val[v] + 2) % 2;
            }
            if (fu > fv){
                fa[fu] = fv;
                val[fu] = (val[v] - node[i].w - val[u] + 2) % 2;
            }
        }
        printf("%d\n", i);
    }
    return 0;
}

HDU3038_How Many Answers Are Wrong

#include<bits/stdc++.h>
using namespace std;
static const int Maxn = 2e5+10;
int fa[Maxn];
int r[Maxn];
void Init(int N){
    for(int i = 0; i <= N; i++){
        fa[i] = i; r[i] = 0;
    } 
}
int Find(int x){
    if(x != fa[x]){
        int pre = fa[x];
        fa[x] = Find(fa[x]);
        r[x] += r[pre];
    }
    return fa[x];
}
bool Query(int x, int y, int sum){// (x-1, y] 左闭右开 
    int fx = Find(x), fy = Find(y);
    if(fx == fy){
        if(r[x] + sum == r[y]) return true;
        else return false;
    }
    fa[fy] = fx;
    r[fy] = r[x] + sum - r[y];
    return true;
}
int main(){
    int N, M, x, y, sum, ans;
    //多组测试数据(题目好像没说,卡了我好久 
    while(scanf("%d%d", &N, &M) != EOF){ 
        ans = 0;
        Init(N);
        while(M--){
            scanf("%d%d%d", &x, &y, &sum);
            if(!Query(x - 1, y, sum)) ans++;
        }
        printf("%d\n", ans);
    }
    return 0;
}

最后贴个网上找的可持久化并查集模板题的题解,看了好久终于看懂了 自己打的话估计bug连连
有时间补几道可持久化的题 不可能的 TMD好难

#include<bits/stdc++.h>
#define N 301000
using namespace std;
template<typename T>inline void read(T &x)
{
    x=0;
    static int p;p=1;
    static char c;c=getchar();
    while(!isdigit(c)){if(c=='-')p=-1;c=getchar();}
    while(isdigit(c)) {x=(x<<1)+(x<<3)+(c-48);c=getchar();}
    x*=p;
}
int n,m;
int L[N*30],R[N*30],fa[N*30],dep[N*30];
int root[N*30];
namespace Persistant_Union_Set
{
#define Mid ((l+r)>>1)
#define lson L[rt],l,Mid
#define rson R[rt],Mid+1,r
    int cnt;
    void build(int &rt,int l,int r)
    {
        rt=++cnt;
        if(l==r){fa[rt]=l;return ;}
        build(lson);build(rson);
    }
    void merge(int last,int &rt,int l,int r,int pos,int Fa)
    {
        rt=++cnt;L[rt]=L[last],R[rt]=R[last];
        if(l==r)
        {
            fa[rt]=Fa;
            dep[rt]=dep[last];
            return;
        }
        if(pos<=Mid)merge(L[last],lson,pos,Fa);
        else merge(R[last],rson,pos,Fa);
    }
    void update(int rt,int l,int r,int pos)
    {
        if(l==r){dep[rt]++;return ;}
        if(pos<=Mid)update(lson,pos);
        else update(rson,pos);
    }
    int query(int rt,int l,int r,int pos)
    {
        if(l==r)return rt;
        if(pos<=Mid)return query(lson,pos);
        else return query(rson,pos);
    }
    int find(int rt,int pos)
    {
        int now=query(rt,1,n,pos);
        if(fa[now]==pos)return now;
        return find(rt,fa[now]);
    }
#undef Mid
#undef lson
#undef rson
}
using namespace Persistant_Union_Set;
int main()
{
    read(n);read(m);
    build(root[0],1,n);
    for(int i=1;i<=m;i++)
    {
        static int opt,x,y;
        read(opt);read(x);
        if(opt==1)
        {
            read(y);
            static int posx,posy;
            root[i]=root[i-1];
            posx=find(root[i],x);posy=find(root[i],y);
            if(fa[posx]!=fa[posy])
            {
                if(dep[posx]>dep[posy])swap(posx,posy);
                merge(root[i-1],root[i],1,n,fa[posx],fa[posy]);
                if(dep[posx]==dep[posy])update(root[i],1,n,fa[posy]);
            }
        }
        else if(opt==2)root[i]=root[x];
        else if(opt==3)
        {
            read(y);
            root[i]=root[i-1];
            static int posx,posy;
            posx=find(root[i],x);posy=find(root[i],y);
            if(fa[posx]==fa[posy])puts("1");
            else puts("0");
        }
    }
    return 0;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,258评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,335评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,225评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,126评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,140评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,098评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,018评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,857评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,298评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,518评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,400评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,993评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,638评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,661评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容