您的位置:首页 > 其它

codevs1301 任务分配(容斥原理)

2017-08-22 17:07 323 查看


1301 任务分配

 

2003年浙江省队选拔赛

 时间限制: 1 s

 空间限制: 128000 KB

 题目等级 : 大师 Master


题解

题目描述 Description

有N位工作人员,同时有N项任
4000
务, 每人必须承担一项任务,若给出某人不能从事的某些任务, 问要安排好工作,共有多少种方案?

输入描述 Input Description

输入文件第1行为N(1<=N<=100), 以下N行,其中第i+1行表示第i个人不能从事的任务编号, 任务之间用空隔分开, 若第i个人没有限制条件,则第i+1行为空行, 所有人员不能从事的任务之和不大于25。

输出描述 Output Description

输出文件只有1行,为所有满足条件的分配方案数。

样例输入 Sample Input

  4
  2
  2 3
  3 4
  4

样例输出 Sample Output

4

数据范围及提示 Data Size & Hint

如题
//dfs实现容斥,全都搜了一遍,但是数据的cnt最大为23
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<sstream>
#include<string>
using namespace std;
//下面为大数模板
const int MAXN=600;
struct bign {
int len, s[MAXN];
bign () {
memset(s, 0, sizeof(s));
len = 1;
}
bign (int num) {
*this = num;
}
bign (const char *num) {
*this = num;
}
bign operator = (const int num) {
char s[MAXN];
sprintf(s, "%d", num);
*this = s;
return *this;
}
bign operator = (const char *num) {
for(int i = 0; num[i] == '0'; num++) ; //去前导0
len = strlen(num);
for(int i = 0; i < len; i++) s[i] = num[len-i-1] - '0';
return *this;
}
bign operator + (const bign &b) const { //+
bign c;
c.len = 0;
for(int i = 0, g = 0; g || i < max(len, b.len); i++) {
int x = g;
if(i < len) x += s[i];
if(i < b.len) x += b.s[i];
c.s[c.len++] = x % 10;
g = x / 10;
}
return c;
}
bign operator += (const bign &b) {
*this = *this + b;
return *this;
}
void clean() {
while(len > 1 && !s[len-1]) len--;
}
bign operator * (const bign &b) { //*
bign c;
c.len = len + b.len;
for(int i = 0; i < len; i++) {
for(int j = 0; j < b.len; j++) {
c.s[i+j] += s[i] * b.s[j];
}
}
for(int i = 0; i < c.len; i++) {
c.s[i+1] += c.s[i]/10;
c.s[i] %= 10;
}
c.clean();
return c;
}
bign operator *= (const bign &b) {
*this = *this * b;
return *this;
}
bign operator - (const bign &b) {
bign c;
c.len = 0;
for(int i = 0, g = 0; i < len; i++) {
int x = s[i] - g;
if(i < b.len) x -= b.s[i];
if(x >= 0) g = 0;
else {
g = 1;
x += 10;
}
c.s[c.len++] = x;
}
c.clean();
return c;
}
bign operator -= (const bign &b) {
*this = *this - b;
return *this;
}
bign operator / (const bign &b) {
bign c, f = 0;
for(int i = len-1; i >= 0; i--) {
f = f*10;
f.s[0] = s[i];
while(f >= b) {
f -= b;
c.s[i]++;
}
}
c.len = len;
c.clean();
return c;
}
bign operator /= (const bign &b) {
*this = *this / b;
return *this;
}
bign operator % (const bign &b) {
bign r = *this / b;
r = *this - r*b;
return r;
}
bign operator %= (const bign &b) {
*this = *this % b;
return *this;
}
bool operator < (const bign &b) {
if(len != b.len) return len < b.len;
for(int i = len-1; i >= 0; i--) {
if(s[i] != b.s[i]) return s[i] < b.s[i];
}
return false;
}
bool operator > (const bign &b) {
if(len != b.len) return len > b.len;
for(int i = len-1; i >= 0; i--) {
if(s[i] != b.s[i]) return s[i] > b.s[i];
}
return false;
}
bool operator == (const bign &b) {
return !(*this > b) && !(*this < b);
}
bool operator != (const bign &b) {
return !(*this == b);
}
bool operator <= (const bign &b) {
return *this < b || *this == b;
}
bool operator >= (const bign &b) {
return *this > b || *this == b;
}
string str() const {
string res = "";
for(int i = 0; i < len; i++) res = char(s[i]+'0') + res;
return res;
}
};

istream& operator >> (istream &in, bign &x) {
string s;
in >> s;
x = s.c_str();
return in;
}

ostream& operator << (ostream &out, const bign &x) {
out << x.str();
return out;
}
//上面为大数模板
bign f[120];
char buf[1000];
int x[105],y[105];
int visx[200],visy[200];
int n,cnt,c[105];
void dfs(int cur,int num) {
c[num]++;
for(int i=cur+1; i<cnt; ++i)
if(!visx[x[i]]&&!visy[y[i]]) {
visx[x[i]]=visy[y[i]]=1;
dfs(i,num+1);
visx[x[i]]=visy[y[i]]=0;
}
}
int main() {
scanf("%d ",&n);
f[1]=f[0]=1;
for(int i=2; i<=n; ++i)
f[i]=f[i-1]*i;
string tmp;
for(int i=1; i<=n; ++i) {
/*莫名出错
gets(buf);
int v;
char *p = strtok(buf," ");
while(p) {
sscanf(p,"%d",&v);
x[cnt]=i;
y[cnt++]=v;
p = strtok(NULL," ");
}
*/
int v;
string readline; // 不要定义在循环外, 因为如果没有读入readline, 会自动保留上次结果.
getline(cin, readline);
stringstream ss(readline);
while(ss >> v) {
x[cnt] = i;
y[cnt++] = v;
}
}
c[0]=1;
for(int i=0; i<cnt; ++i) {
visx[x[i]]=visy[y[i]]=1;
dfs(i,1);
visx[x[i]]=visy[y[i]]=0;

}
bign ans=0;
for(int i=0; i<n; i+=2)
ans+=f[n-i]*c[i];
for(int i=1; i<n; i+=2)
ans-=f[n-i]*c[i];
cout<<ans<<endl;
return 0;
}
/*
4
2
2 3
3 4
4
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: