这题我自我感觉特恶心
因为就是这么一道题我听取WA声一片
不信找洛谷 L_Y_T P3275 的做题记录……
好了,废话少说,步入正题。
题目描述
幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求。幼儿园的糖果总是有限的,lxhgww想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。
输入输出格式
输入格式:
输入的第一行是两个整数N,K。接下来K行,表示这些点需要满足的关系,每行3个数字,X,A,B。如果X=1, 表示第A个小朋友分到的糖果必须和第B个小朋友分到的糖果一样多;如果X=2, 表示第A个小朋友分到的糖果必须少于第B个小朋友分到的糖果;如果X=3, 表示第A个小朋友分到的糖果必须不少于第B个小朋友分到的糖果;如果X=4, 表示第A个小朋友分到的糖果必须多于第B个小朋友分到的糖果;如果X=5, 表示第A个小朋友分到的糖果必须不多于第B个小朋友分到的糖果;
输出格式:
输出一行,表示lxhgww老师至少需要准备的糖果数,如果不能满足小朋友们的所有要求,就输出-1。
输入输出样例
输入样例#1:
5 7
1 1 2
2 3 2
4 4 1
3 4 5
5 4 5
2 3 5
4 5 1
输出样例#1:
11
这道题有五种操作
如果X=1, 表示第A个小朋友分到的糖果必须和第B个小朋友分到的糖果一样多;如果X=2, 表示第A个小朋友分到的糖果必须少于第B个小朋友分到的糖果;如果X=3, 表示第A个小朋友分到的糖果必须不少于第B个小朋友分到的糖果;如果X=4, 表示第A个小朋友分到的糖果必须多于第B个小朋友分到的糖果;如果X=5, 表示第A个小朋友分到的糖果必须不多于第B个小朋友分到的糖果;
这样的话,我们就可以对其进行分析
首先,
如果 x == 1 的话 , 就是A和B的糖果相等
换言之,就是 A == B ,即 A-B < 0 , B-A < 0 ;
换到程序代码上就是 add(a,b,0) ; add(b,a,0) ;
如果 x == 2 的话 , 表示A 的 必须少于B 的. 因为题目要求是求最少要准备的糖果数量,并且A还必须小于B .所以,不难想出,A< B .即A-B < 1 ;即add(a,b,1);
如果 x == 4 的话 , 就和上面讲的一样了!
如果 x == 3 , 那么A的必须不少于B的.让我们试想一下,如果A比B多的话,那么,我们恒可能又要多准备糖果,所以,当A <= B , A-B <
0 时最少;add(A,B,0) ;
如果 x == 5 ,情况相同 .
然后就可以开开心心的看代码了!!
主程序
int main(){
cin >> n >> k ;
int u , v , opt ;
for(int i = 1 ; i<= k ; i ++){
cin >> opt >> u >> v ;
if(opt == 1) add(u , v , 0) , add(v , u , 0) ;
else if(opt == 2){
if(u == v) {
cout << -1 ;
return 0 ;
}add(u,v,1) ;
}
else if(opt == 3) add(v,u,0) ;
else if(opt == 4) {
if(u == v){
cout << -1 ;
return 0 ;
}add(v,u,1) ;
}
else if(opt == 5){
add(u,v,0) ;
}
}
//我们要从0开始
for(int i = n ; i >= 1 ; i --) add(0,i,1) ;
vis[0] = 1 ;
下面是SPFA的函数
//因为我们并没有定义负值,所以我们可以开开心心的用队列版spfa
vis[0] = 1 ;
q.push(0) ;
while(!q.empty()){
int u = q.front() ;
q.pop() ;
vis[u] = 0 ;
if(tot[u] == n-1) {
cout << -1 ;
return 0 ;
}tot[u] ++ ;
for(int i = head[u] ; i ; i = a[i].next){
int v = a[i].to ;
if(dis[v] < dis[u] + a[i].w){
dis[v] = dis[u] + a[i].w ;
if(!vis[v]){
vis[v] = 1 ;
q.push(v) ;
}
}
}
}
in the end , 开开心心的输出
long long ans = 0 ;
for(int i = 1 ; i <= n ; i ++){
ans += dis[i] ;
}
cout << ans ;
return 0 ; //这是个好习惯
开开心心的结束喽!!!
算了,还是补个全代码吧!
#include<iostream>
#include<stdio.h>
#include<queue>
#include<string.h>
#include<algorithm>
#define maxn 300000
using namespace std ;
int n , m , head[maxn] , vis[maxn] , dis[maxn] ;
struct dy{
int from , to , w , next ;
}a[maxn];
queue<int>q ;
int t ;
void add(int x , int y , int z){
a[++t].from = x ;
a[t].to = y ;
a[t].w = z ;
a[t].next = head[x] ;
head[x] = t ;
}int tot [maxn] ;
int k ;
void spfa(){
vis[0] = 1 ;
q.push(0) ;
while(!q.empty()){
int u = q.front() ;
q.pop() ;
vis[u] = 0 ;
if(tot[u] == n-1) {
cout << -1 ;
exit(0) ;
}tot[u] ++ ;
for(int i = head[u] ; i ; i = a[i].next){
int v = a[i].to ;
if(dis[v] < dis[u] + a[i].w){
dis[v] = dis[u] + a[i].w ;
if(!vis[v]){
vis[v] = 1 ;
q.push(v) ;
}
}
}
}
}
int main(){
cin >> n >> k ;
int u , v , opt ;
for(int i = 1 ; i<= k ; i ++){
cin >> opt >> u >> v ;
if(opt == 1) add(u , v , 0) , add(v , u , 0) ;
else if(opt == 2){
if(u == v) {
cout << -1 ;
return 0 ;
}add(u,v,1) ;
}
else if(opt == 3) add(v,u,0) ;
else if(opt == 4) {
if(u == v){
cout << -1 ;
return 0 ;
}add(v,u,1) ;
}
else if(opt == 5){
add(u,v,0) ;
}
}
for(int i = n ; i >= 1 ; i --) add(0,i,1) ;
spfa() ;
long long ans = 0 ;
for(int i = 1 ; i <= n ; i ++){
ans += dis[i] ;
}
cout << ans ;
return 0 ;
}
真的结束
TRUE ENDING