Strategic Game
Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 910 Accepted Submission(s): 354
Your program should find the minimum number of soldiers that Bob has to put for a given tree.
The input file contains several data sets in text format. Each data set represents a tree with the following description:
the number of nodes
the description of each node in the following format
node_identifier:(number_of_roads) node_identifier1 node_identifier2 ... node_identifier
or
node_identifier:(0)
The node identifiers are integer numbers between 0 and n-1, for n nodes (0 < n <= 1500). Every edge appears only once in the input data.
For example for the tree:
the solution is one soldier ( at the node 1).
The output should be printed on the standard output. For each given input data set, print one integer number in a single line that gives the result (the minimum number of soldiers). An example is given in the following table:
4 0:(1) 1 1:(2) 2 3 2:(0) 3:(0) 5 3:(3) 1 4 2 1:(1) 0 2:(0) 0:(0) 4:(0)
1 2//自己实现的时候,由于申请了一个1505*1505的数组,结果超时,参考了网上的代码,但是此代码也有缺陷,由于ma只申请了每个节点后只有//11个节点,此题能过说明测试用例不够强,不推荐此方法,见后面我自己写的代码.
#include<stdio.h>
#include<memory.h>
int ma[1500][11];
int link[15001];
int len[15001];
bool useif[150001];
bool can(int v)
{
for(int u=0;u<len[v];u++)
{
if(!useif[ma[v][u]])
{
useif[ma[v][u]]=1;
if(link[ma[v][u]]==-1||(can(link[ma[v][u]])))
{
link[ma[v][u]]=v;
return 1;
}
}
}
return 0;
}
int main()
{
int x,n,i,ans,m,y,max,num;
while(scanf("%d",&n)!=EOF)
{
memset(len,0,4*n);
num=n;
while(n--)
{
scanf("%d:(%d)",&x,&m);
while(m--&&scanf("%d",&y))
{
ma[x][len[x]++]=y;
ma[y][len[y]++]=x;
}
}
ans=0;
memset(link,-1,4*num);
for(i=0;i<num;i++)
{
memset(useif,0,sizeof(useif));
if(can(i))
ans++;
}
printf("%d/n",ans/2);
}
return 0;
}
//经过几天的思考这种解法是很不完善的,自己就用动态邻接链表和动态临界链表重写了一遍
6868513 | Accepted | 176K | 641MS | 1505B | 2010-05-08 16:53:25 |
//本题目对空间和时间的要求较高,若用邻接矩阵写会超时,若用动态链表写会超内存,//所以这里我们采用的是静态链表。
//这里采用的是匈牙利算法的邻接表形式
//我们要先将图补成二分图,因为1到2有边,2到1也有变,但求的结果要处以2
//由于边的个数最多为顶点的2倍,故开数组的时候要开成顶点的的2倍,否则会出现
//runtime error
#include<iostream>
using namespace std;
//用来表示边,to表示边的另一个定点,next用来记录下一条边的编号
struct Node
{
int to;
int next;
};
//用来表示定点,first用来记录顶点的第一条边的编号,从1开始编号
struct ve
{
int first;
};
Node edge[1505*2];
ve vex[1505];
int used[1505];
//记录当前与y节点相连的x顶点
int link[1505];
int n;
int can(int t)
{
//获取此顶点的第一条边
int temp=vex[t].first;
while(temp!=-1)
{
int to=edge[temp].to;
if(used[to]==0)
{
used[to]=1;
if(link[to]==-1||can(link[to]))
{
link[to]=t;
return 1;
}
}
temp=edge[temp].next;
}
return 0;
}
int res()
{
int sum=0;
memset(link,-1,sizeof(link));
for(int i=1;i<=n;i++)
{
memset(used,0,sizeof(used));
if(can(i))
sum++;
}
return sum;
}
void init()
{
for(int i=1;i<=n;i++)
{
vex[i].first=-1;
}
for(int i=1;i<=2*n;i++)
{
edge[i].next=-1;
edge[i].to=-1;
}
}
int main()
{
int i,j,from,num,to,count;
while(scanf("%d",&n)!=EOF)
{
init();
count=1;
for(i=0;i<n;i++)
{
scanf("%d:(%d)",&from,&num);
from++;
while(num--)
{
scanf("%d",&to);
to++;
int temp=vex[from].first;
bool flag=false;
while(temp!=-1)
{
if(edge[temp].to==to)
{
flag=true;
break;
}
temp=edge[temp].next;
}
if(!flag)
{
//构建静态链表
edge[count].to=to;
edge[count].next=vex[from].first;
vex[from].first=count;
count++;
edge[count].to=from;
edge[count].next=vex[to].first;
vex[to].first=count;
count++;
}
}
}
printf("%d/n",res()/2);
}
return 0;
}
#include<iostream>
using namespace std;
struct Node
{
int to;
Node* next;
};
int used[1515];
Node* edge[1515];
int link[1515];
int n;
//对于左边每个顶点
bool can(int t)
{
for(Node* temp=edge[t];temp;temp=temp->next)
{
int v=temp->to;
if(used[v]==0)
{
used[v]=1;
if(link[v]==-1||can(link[v]))
{
link[v]=t;
return 1;
}
}
}
return 0;
}
int MaxMatch()
{
int num=0;
memset(link,-1,sizeof(link));
for(int i=1;i<=n;i++)
{
memset(used,0,sizeof(used));
if(can(i))
num++;
}
return num;
}
int main()
{
int i,j,from,num,to;
while(scanf("%d",&n)!=EOF)
{
for(i=0;i<n;i++)
{
scanf("%d:(%d)",&from,&num);
from++;
while(num--)
{
scanf("%d",&to);
to++;
Node* temp=new Node;
temp->to=to;
temp->next=edge[from];
edge[from]=temp;
Node* tmp=new Node;
tmp->to=from;
tmp->next=edge[to];
edge[to]=tmp;
}
}
printf("%d/n",MaxMatch()/2);
for(i=1;i<=n;i++)
edge[i]=NULL;
}
}