2020.7.27【算协集训】拓扑排序

网页链接:传送门
密码:HPUACM

A - Genealogical tree (POJ-2367)

The system of Martians’ blood relations is confusing enough. Actually, Martians bud when they want and where they want. They gather together in different groups, so that a Martian can have one parent as well as ten. Nobody will be surprised by a hundred of children. Martians have got used to this and their style of life seems to them natural.
And in the Planetary Council the confusing genealogical system leads to some embarrassment. There meet the worthiest of Martians, and therefore in order to offend nobody in all of the discussions it is used first to give the floor to the old Martians, than to the younger ones and only than to the most young childless assessors. However, the maintenance of this order really is not a trivial task. Not always Martian knows all of his parents (and there’s nothing to tell about his grandparents!). But if by a mistake first speak a grandson and only than his young appearing great-grandfather, this is a real scandal.
Your task is to write a program, which would define once and for all, an order that would guarantee that every member of the Council takes the floor earlier than each of his descendants.
Input
The first line of the standard input contains an only number N, 1 <= N <= 100 — a number of members of the Martian Planetary Council. According to the centuries-old tradition members of the Council are enumerated with the natural numbers from 1 up to N. Further, there are exactly N lines, moreover, the I-th line contains a list of I-th member’s children. The list of children is a sequence of serial numbers of children in a arbitrary order separated by spaces. The list of children may be empty. The list (even if it is empty) ends with 0.
Output
The standard output should contain in its only line a sequence of speakers’ numbers, separated by spaces. If several sequences satisfy the conditions of the problem, you are to write to the standard output any of them. At least one such sequence always exists.

Sample InputSample Output
5
0
4 5 1 0
1 0
5 3 0
3 0
2 4 5 3 1

分析

题意:火星人没有家庭观,每个人可能有多个父母或是多个崽子。一坨火星人开会的时候,需要按辈分发言——辈分大的先发言,辈分小的后发言。因此也不会出现自环(不会出现我是你爹,你又是我爹的情况)。所以这题可以利用拓扑排序编写代码。
测试用例图示:

代码

#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
const ll maxn=110;

int N,index,x;
int ans[maxn],in[maxn];
vector<int> ma[maxn];

void topo() //拓扑排序
{
	index=0;
	queue<int> q;
	for(int i=1;i<=N;i++)
	{
		if(!in[i])
		{
			q.push(i);
		}
	}
	while(!q.empty())
	{
		int x=q.front();
		ans[index++]=x;
		q.pop();
		for(int i=0;i<ma[x].size();i++)
		{
			int y=ma[x][i];
			in[y]--;
			if(!in[y])
			{
				q.push(y);
			}
		}
	}
}

int main()
{
	scanf("%d",&N);
	for(int i=1;i<=N;i++)
	{
		scanf("%d",&x);
		while(x)
		{
			ma[i].push_back(x);
			in[x]++;
			scanf("%d",&x);
		}
	}
	topo();
	for(int i=0;i<index;i++)
	{
		if(i!=0)	printf(" ");
		printf("%d",ans[i]);
	}
	return 0;
}

B - Window Pains (POJ-2585)

Boudreaux likes to multitask, especially when it comes to using his computer. Never satisfied with just running one application at a time, he usually runs nine applications, each in its own window. Due to limited screen real estate, he overlaps these windows and brings whatever window he currently needs to work with to the foreground. If his screen were a 4 x 4 grid of squares, each of Boudreaux’s windows would be represented by the following 2 x 2 windows:

When Boudreaux brings a window to the foreground, all of its squares come to the top, overlapping any squares it shares with other windows. For example, if window 1and then window 2 were brought to the foreground, the resulting representation would be:
If window 4 were then brought to the foreground: . . . and so on . . .
Unfortunately, Boudreaux’s computer is very unreliable and crashes often. He could easily tell if a crash occurred by looking at the windows and seeing a graphical representation that should not occur if windows were being brought to the foreground correctly. And this is where you come in . . .
Input
Input to this problem will consist of a (non-empty) series of up to 100 data sets. Each data set will be formatted according to the following description, and there will be no blank lines separating data sets.
A single data set has 3 components:
1.Start line - A single line:
START
2.Screen Shot - Four lines that represent the current graphical representation of the windows on Boudreaux’s screen. Each position in this 4 x 4 matrix will represent the current piece of window showing in each square. To make input easier, the list of numbers on each line will be delimited by a single space.
3.End line - A single line:
END
After the last data set, there will be a single line:
ENDOFINPUT
Note that each piece of visible window will appear only in screen areas where the window could appear when brought to the front. For instance, a 1 can only appear in the top left quadrant.
Output
For each data set, there will be exactly one line of output. If there exists a sequence of bringing windows to the foreground that would result in the graphical representation of the windows on Boudreaux’s screen, the output will be a single line with the statement:
THESE WINDOWS ARE CLEAN
Otherwise, the output will be a single line with the statement:
THESE WINDOWS ARE BROKEN

Sample InputSample Output
START
1 2 3 3
4 5 6 6
7 8 9 9
7 8 9 9
END
START
1 1 3 3
4 1 3 3
7 7 9 9
7 7 9 9
END
ENDOFINPUT
THESE WINDOWS ARE CLEAN
THESE WINDOWS ARE BROKEN

分析

4 ∗ 4 4*4 44 的矩阵中有 9 9 9 个程序窗口,每个窗口占用 2 ∗ 2 2*2 22 矩阵的空间,编号为 1   9 1~9 1 9 。如图:

在这些窗口中有相互覆盖的关系。给出9*9的数字矩阵,不同的数字表示不同的窗口。问这样的相互覆盖关系是否合理。

这是每个格子都可以有的数字:
因此可以先初始化窗口。在 i i i j j j 列的格子中,有一些可以放的数,而如今存放的是某一个确定的数,那么在这个格子中,这个确定的数就覆盖了除它以外的所有数。由此可以利用拓扑排序,看看是否有环,如果有环就说明不合理,反之则合理。(如:对于第二行第二列的格子, 1 1 1 可以覆盖 2 2 2 2 2 2 也可以覆盖 1 1 1 ,但是只能在两种情况中选择一种情况,不能同时覆盖对方)

代码

#include<iostream>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
const ll maxn=110;

string s;
int in[maxn];
vector<int> ma[maxn];
vector<int> win[maxn][maxn];	//每个格子应该有的数字
int inputwin[maxn][maxn];		//每个格子实际有的数字 

void init()			//初始化变量 
{
	memset(in,0,sizeof(in));
	for(int i=0;i<=9;i++)
	{
		ma[i].clear();
	}
}

void windowinit()	//初始化窗口 
{
	int num=0;
	for(int i=0;i<3;i++)
	{
		for(int j=0;j<3;j++)
		{
			num++;
			win[i][j].push_back(num);
			win[i+1][j].push_back(num);
			win[i][j+1].push_back(num);
			win[i+1][j+1].push_back(num);
		}
	}
}

void add(int i,int j)
{
	for(int k=0;k<win[i][j].size();k++)
	{
		int x=inputwin[i][j];
		int y=win[i][j][k];
		if(x!=y)
		{
			in[y]++;
			ma[x].push_back(y);
		}
	}
}

void creat()		//建图
{
	for(int i=0;i<4;i++)
	{
		for(int j=0;j<4;j++)
		{
			cin>>inputwin[i][j];
			add(i,j);
		}
	}
}

void topo()			//拓扑排序 
{
	queue<int> q;
	for(int i=1;i<=9;i++)
	{
		if(!in[i])
		{
			q.push(i);
		}
	}
	while(!q.empty())
	{
		int x=q.front();
		q.pop();
		for(int i=0;i<ma[x].size();i++)
		{
			int y=ma[x][i];
			in[y]--;
			if(!in[y])
			{
				q.push(y);
			}
		}
	}
}

void output()		//输出 
{
	bool flag=true;
	for(int i=1;i<=9;i++)
	{
		if(in[i])
		{
			flag=false;
			break;
		}
	}
	if(flag)	cout<<"THESE WINDOWS ARE CLEAN\n";
	else	cout<<"THESE WINDOWS ARE BROKEN\n";
}

int main()
{
	windowinit();	//初始化窗口 
	while(cin>>s)
	{
		if(s=="ENDOFINPUT")	break;
		init();		//初始化变量 
		creat();	//建图 
		cin>>s;		//收一下结尾的END
		topo();		//拓扑排序 
		output();	//输出 
	}
	return 0;
}

C - 确定比赛名次 (HDU-1285)

有N个比赛队(1<=N<=500),编号依次为1,2,3,。。。。,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前。现在请你编程序确定排名。
Input
输入有若干组,每组中的第一行为二个数N(1<=N<=500),M;其中N表示队伍的个数,M表示接着有M行的输入数据。接下来的M行数据中,每行也有两个整数P1,P2表示即P1队赢了P2队。
Output
给出一个符合要求的排名。输出时队伍号之间有空格,最后一名后面没有空格。
其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。

Sample InputSample Output
4 3
1 2
2 3
4 3
1 2 4 3

分析

这题稍微和模板不一样的地方,就是在没有直接的前后关系的条件下,要求编号小的队伍排在前面。因此我这用了优先队列,使得每次队列中靠前的都是编号小的队伍。(其他应该都没变)

代码

#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<functional>//杭电oj要加上这个,才能用priority_queue<int,vector<int>,greater<int>>
using namespace std;
typedef long long ll;
const ll maxn=1100;

int N,M,p1,p2,index;
int ans[maxn],in[maxn];	//ans存放结果,in存放入度数
vector<int> ma[maxn];	//ma存图

void topo()	//拓扑排序
{
	index=0;
	priority_queue<int,vector<int>,greater<int>> q;
	for(int i=1;i<=N;i++)
	{
		if(!in[i])
		{
			q.push(i);
		}
	}
	while(!q.empty())
	{
		int x=q.top();
		ans[index++]=x;
		q.pop();
		for(int i=0;i<ma[x].size();i++)
		{
			int y=ma[x][i];
			in[y]--;
			if(!in[y])
			{
				q.push(y);
			}
		}
	}
}

int main()
{
	while(~scanf("%d%d",&N,&M))
	{
		memset(ans,0,sizeof(ans));
		memset(in,0,sizeof(in));
		for(int i=0;i<maxn;i++)
			ma[i].clear();
		for(int i=0;i<M;i++)
		{
			scanf("%d%d",&p1,&p2);
			ma[p1].push_back(p2);
			in[p2]++;
		}
		topo();
		for(int i=0;i<index;i++)
		{
			if(i!=0)	printf(" ");
			printf("%d",ans[i]);
		}
		printf("\n");
	}
	return 0;
}

D - 产生冠军 (HDU-2094)

有一群人,打乒乓球比赛,两两捉对撕杀,每两个人之间最多打一场比赛。
球赛的规则如下:
如果A打败了B,B又打败了C,而A与C之间没有进行过比赛,那么就认定,A一定能打败C。
如果A打败了B,B又打败了C,而且,C又打败了A,那么A、B、C三者都不可能成为冠军。
根据这个规则,无需循环较量,或许就能确定冠军。你的任务就是面对一群比赛选手,在经过了若干场撕杀之后,确定是否已经实际上产生了冠军。
Input
输入含有一些选手群,每群选手都以一个整数n(n<1000)开头,后跟n对选手的比赛结果,比赛结果以一对选手名字(中间隔一空格)表示,前者战胜后者。如果n为0,则表示输入结束。
Output
对于每个选手群,若你判断出产生了冠军,则在一行中输出“Yes”,否则在一行中输出“No”。

Sample InputSample Output
3
Alice Bob
Smith John
Alice Smith
5
a c
c d
d e
b e
a d
0
Yes
No

分析

这题有涉及到我最不擅长的字符串……所以我用的方法是先把字符串变成数字编号再整。不过这题有很多方法,这里都略讲一下。

不管是哪种写法,主要思想都是一致的,即最后的赢家只能有一个——因为我们只想知道冠军是否产生,不考虑中间的排名。因此在数据输入结束后,可以统计一下最后赢家的个数(不论赢过几次,只要输过一次,都算输家),如果最后的赢家只有一个,就是Yes,反之则是No。

  1. 第一种写法
    字符串变成数字编号,进行拓扑排序,计算入度为 0 0 0 的个数有几个。入度为 0 0 0 的点只有一个,就输出“Yes”,反之输出“No”。
  2. 第二种写法
    m a p map map 记录数据,用 c o u n t count count 函数判断输入的字符串是否曾经出现过——对于 m a p map map,出现过就是 1 1 1 ,没出现过就是 0 0 0 ——如果出现过,只需要把输家标记成 f a l s e false false ;如果没有出现过,就把它添加进去并标记为 t r u e true true(输家也标记成 t r u e true true 是因为后面不管出没出现过暑假都会标记成 f a l s e false false ,因此不会对结果产生影响,当然也可以直接把输家标记成 f a l s e false false )。最后遍历并统计被标记成 t r u e true true 的有几个,只有一个就输出“Yes”,反之输出“No”。
  3. 第三种写法
    s e t set set 分别存放总共出现过的人和输家, s 1 s1 s1 存放总人数, s 2 s2 s2 存放输家,最后只需要计算总人数减去输家个数,判断是否为 1 1 1,如果是则说明有冠军,反之则无。

代码

  1. 第一种写法
    #include<cstdio>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const ll maxn=1010;
    
    int n,x,y,cnt;
    int in[maxn];
    char str[maxn][maxn/10],str1[maxn/10],str2[maxn/10];
    
    int search(char *s)
    {
    	int i;
    	for(i=0;i<cnt;i++)
    	{
    		if(strcmp(str[i],s)==0)	//出现过名字是s的人 
    			return i;
    	}
    	strcpy(str[i],s);	//没出现过名字是s的人 
    	return cnt++;	//跳出for循环的时候i=cnt,现在增加了一个人,总人数+1 
    }
    
    void topo() 
    {
    	int flag=0;
    	for(int i=0;i<cnt;i++)
    	{
    		if(in[i]==0)
    		{
    			flag++;
    		}
    	}
    	if(flag==1)	printf("Yes\n");
    	else	printf("No\n");
    }
    
    int main()
    {
    	while(~scanf("%d",&n))
    	{
    		if(n==0)	break;
    		memset(in,0,sizeof(in));
    		cnt=0;
    		for(int i=1;i<=n;i++)
    		{
    			scanf("%s%s",str1,str2);
    			x=search(str1);
    			y=search(str2);
    			in[y]++;
    		}
    		topo();
    	}
    	return 0;
    }
    
  2. 第二种写法
    #include<iostream>
    #include<cstring>
    #include<map>
    using namespace std;
    typedef long long ll;
    const ll maxn=1010;
    
    int n,cnt;
    string str1,str2;
    
    int main()
    {
    	while(cin>>n)
    	{
    		if(n==0)	break;
    		map<string,bool> mp;
    		while(n--)
    		{
    			cin>>str1>>str2;
    			if(!mp.count(str1))	mp[str1]=true;
    			if(!mp.count(str2))	mp[str2]=true;
    			mp[str2]=false;
    		}
    		cnt=0;
    		for(auto it=mp.begin();it!=mp.end();it++)
    		{
    			if(it->second==true)
    				cnt++;
    		}
    		if(cnt==1)	cout<<"Yes\n";
    		else	cout<<"No\n";
    	}
    	return 0;
    }
    
  3. 第三种写法
    #include<iostream>
    #include<cstring>
    #include<set>
    using namespace std;
    typedef long long ll;
    const ll maxn=1010;
    
    int n;
    string str1,str2;
    
    int main()
    {
    	while(cin>>n)
    	{
    		if(n==0)	break;
    		set<string> s1,s2;	//s1记录总人数,s2记录输过的人数 
    		while(n--)
    		{
    			cin>>str1>>str2;
    			s1.insert(str1);
    			s1.insert(str2);
    			s2.insert(str2);
    		}
    		if(s1.size()-s2.size()==1)	cout<<"Yes\n";
    		else	cout<<"No\n";
    	}
    	return 0;
    }
    

E - Legal or Not (HDU-3342)

我们都知道一个师傅可以有很多徒弟,一个徒弟也可以有很多师傅,这是合法的。然而,一些师徒持有非法关系。以a和b为例,a是b的师傅,同时b也是a的师傅,这是违法的!为了避免这种情况,请帮助我们判断他们的关系是否合法。
请注意,师徒关系是可传递的。这意味着如果A是B的师傅,B是C的师傅,那么A也是C的师傅。
Input
输入包含多组测试样例。对于每组样例,第一行包含两个整数, N (人数) and M (关系数)(2 <= N, M <= 100). 接下来 M 行 ,每行包含一对 (x, y) ,这表示x是y的师傅,y是x的徒弟。当输入N = 0时结束.
为了让题目简单,我们给每个人一个编号(0, 1, 2,…, N-1). 我们使用编号代替他们的名字
Output
对每个样例来说,如果关系合法输出YES,否则输出NO
If it is legal, output “YES”, otherwise “NO”.

Sample InputSample Output
3 2
0 1
1 2
2 2
0 1
1 0
0 0
YES
NO

分析

这题感觉就是拓扑排序的模板题。经过拓扑排序后,如果 i n d e x ≠ n index≠n index=n 或是有元素的入度不为 0 0 0 ,就说明有环(a是b的师傅,同时b也是a的师傅),这样就是不合法的,反之就是合法的。

代码

#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
const ll maxn=110;

int N,M,index,x,y;
int ans[maxn],in[maxn];
vector<int> ma[maxn];

void topo() 
{
	index=0;
	queue<int> q;
	for(int i=0;i<N;i++)
	{
		if(!in[i])
		{
			q.push(i);
		}
	}
	while(!q.empty())
	{
		int x=q.front();
		ans[index++]=x;
		q.pop();
		for(int i=0;i<ma[x].size();i++)
		{
			int y=ma[x][i];
			in[y]--;
			if(!in[y])
			{
				q.push(y);
			}
		}
	}
	if(index!=N)	printf("NO\n");
	else	printf("YES\n");
}

int main()
{
	while(~scanf("%d%d",&N,&M))
	{
		if(N==0 && M==0)	break;
		memset(ans,0,sizeof(ans));
		memset(in,0,sizeof(in));
		for(int i=0;i<maxn;i++)
			ma[i].clear();
		for(int i=0;i<M;i++)
		{
			scanf("%d%d",&x,&y);
			ma[x].push_back(y);
			in[y]++;
		}
		topo();
	}
	return 0;
}

F - Reward (HDU-2647)

格林剧团发工资的时候又到辣,格林剧团来到了圣巢,他们入乡随俗,将工资用圣巢的货币–吉欧来结算。格林团长决定每个人的最低工资是888吉欧,同时有些工人希望自己的工资要比其他某个人的高。格林团长希望在尽可能的少发工资的同时满足其他所有人的需求。请你帮帮格林团长吧,格林团长会邀请你与其在剧团内共舞一场猩红仪式。
Input
题目包含多组输入 第一行输入两个整数n,m,分别表示工人的数量与需求的个数。 接下来m行,每一行都包含两个整数a和b,表示a的工资必须比b的工资高
Output
对于每一组输入,输出格林团长最少花费的吉欧数量。如果格林团长不能满足所有人的需求,输出-1.

Sample InputSample Output
2 1
1 2
2 2
1 2
2 1
1777
-1

分析

这道题如果没有工资高低之分,答案就是 s u m = 888 ∗ n sum=888*n sum=888n 。然后我们来考虑工资高低的问题,如图所示:(红字是最少要高多少)

我们可以看出,刚开始入度为 0 0 0 的点是加的比较多的,但是如果正向做的话很难计算到底要加多少,因此我们考虑反向建图,如图所示:
这样就很直观地发现,反向建图计算就非常方便。假如设点 x x x 的工资最少要高 m o n e y [ x ] money[x] money[x] ,那么它的所有子点 y y y 最少要高 m o n e y [ y ] = m a x ( m o n e y [ y ] , m o n e y [ x ] + 1 ) money[y]=max(money[y],money[x]+1) money[y]=max(money[y],money[x]+1) 。最后就只要计算这些 m o n e y [ i ] money[i] money[i] 的和是多少,与前面的 888 ∗ n 888*n 888n 相加就可以了。

代码

#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
const ll maxn=10010;

int n,m,index,x,y;
int in[maxn],money[maxn];
vector<int> ma[maxn];
ll sum;

void topo() 
{
	index=0;
	queue<int> q;
	for(int i=1;i<=n;i++)
	{
		if(!in[i])
		{
			q.push(i);
		}
	}
	while(!q.empty())
	{
		int x=q.front();
		index++;
		q.pop();
		for(int i=0;i<ma[x].size();i++)
		{
			int y=ma[x][i];
			in[y]--;
			if(!in[y])
			{
				q.push(y);
				money[y]=max(money[y],money[x]+1);
			}
		}
	}
	if(index!=n)	printf("-1\n");	//不合法(有环)
	else
	{
		sum=888*n;
		for(int i=1;i<=n;i++)
		{
			sum+=money[i];
		}
		printf("%lld\n",sum);
	}
}

int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		memset(in,0,sizeof(in));
		memset(money,0,sizeof(money));
		for(int i=0;i<maxn;i++)
			ma[i].clear();
		for(int i=0;i<m;i++)
		{
			scanf("%d%d",&x,&y);
			ma[y].push_back(x);	//反向存图 
			in[x]++;
		}
		topo();
	}
	return 0;
}

G - Ordering Tasks (UVA-10305)

John has n tasks to do. Unfortunately, the tasks are not independent and the execution of one task is only possible if other tasks have already been executed.
Input
The input will consist of several instances of the problem. Each instance begins with a line containing two integers, 1≤n≤100 and m. n is the number of tasks (numbered from 1 to n) and m is the number of direct precedence relations between tasks. After this, there will be m lines with two integers i and j, representing the fact that task i must be executed before task j.
An instance with n= m= 0 will finish the input.
Output
For each instance, print a line with n integers representing the tasks in a possible order of execution.

Sample InputSample Output
5 4
1 2
2 3
1 3
1 5
0 0
1 4 2 5 3

分析

模板题,但是变量名是index蜜汁会错,改一下名字就可以了。

代码

#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
const ll maxn=1100;

int n,m,p1,p2,idex;
int ans[maxn],in[maxn];
vector<int> ma[maxn];

void topo() 
{
	idex=0;
	queue<int> q;
	for(int i=1;i<=n;i++)
	{
		if(!in[i])
		{
			q.push(i);
		}
	}
	while(!q.empty())
	{
		int x=q.front();
		ans[idex++]=x;
		q.pop();
		for(int i=0;i<ma[x].size();i++)
		{
			int y=ma[x][i];
			in[y]--;
			if(!in[y])
			{
				q.push(y);
			}
		}
	}
}

int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		if(n==0 && m==0)	break;
		memset(ans,0,sizeof(ans));
		memset(in,0,sizeof(in));
		for(int i=0;i<maxn;i++)
			ma[i].clear();
		for(int i=0;i<m;i++)
		{
			scanf("%d%d",&p1,&p2);
			ma[p1].push_back(p2);
			in[p2]++;
		}
		topo();
		for(int i=0;i<idex;i++)
		{
			if(i!=0)	printf(" ");
			printf("%d",ans[i]);
		}
		printf("\n");
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值