一、Stockbroker Grapevine
题目:Stockbrokers are known to overreact to rumours. You have been contracted to develop a method of spreading disinformation amongst the stockbrokers to give your employer the tactical edge in the stock market. For maximum effect, you have to spread the rumours in the fastest possible way.
Unfortunately for you, stockbrokers only trust information coming from their "Trusted sources" This means you have to take into account the structure of their contacts when starting a rumour. It takes a certain amount of time for a specific stockbroker to pass the rumour on to each of his colleagues. Your task will be to write a program that tells you which stockbroker to choose as your starting point for the rumour, as well as the time it will take for the rumour to spread throughout the stockbroker community. This duration is measured as the time needed for the last person to receive the information.
思路:这是一道利用floyd算法解决的问题,将该题图化,利用floyd算法求解最小路径
#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 105;
int d[N][N];
int n, mmin;
void init(){
mmin = INF;
for( int i = 0; i < N; i++ )
for( int j = 0; j < N; j++ )
d[i][j] = i == j ? 0 : INF;
}
void floyd(){
for( int k = 1; k <= n; k++ )
for( int i = 1; i <= n; i++ )
for( int j = 1; j <= n; j++ )
d[i][j] = min( d[i][j], d[i][k]+d[k][j] );
int mi = INF, ma, pos;
for(int i = 1; i <= n; i++){
ma = -1;
for(int j = 1; j <= n; j++)
if(i != j && ma < d[i][j])
ma = d[i][j];
if(ma < mi){
mi = ma;
pos = i;
}
}
if( mi < INF ) printf("%d %d\n",pos, mi);
else printf("disjoint\n");
}
int main()
{
int t, u, v;
while(~scanf("%d",&n)&&n){
init();
for( int i = 1; i <= n; i++ ){
cin>>t;
for( int j = 0; j < t; j++ ){
cin>>u>>v;
d[i][u] = v;
}
}
floyd();
}
return 0;
}
二、树的直径
题目:一棵树的直径就是这棵树上存在的最长路径。现在有一棵 nn 个节点的树,现在想知道这棵树的直径包含的边的个数是多少?
思路:利用两次dfs求出树的直径,因为题中没有边的权重,全部赋值为1即可
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define LL long long
const int MOD = 1E9+7;
const int N = 1e6+5;
const int dx[] = {-1,1,0,0,-1,-1,1,1};
const int dy[] = {0,0,-1,1,-1,1,-1,1};
using namespace std;
struct Edge{
int w;
int from,to;
int next;
}edge[N];
int head[N],num=0;
int n,m;
int dis[N*2];
bool vis[N];
int start,endd;
void addEdge(int from,int to,int w) {
edge[++num].to=to;
edge[num].w=w;
edge[num].next=head[from];
edge[num].from=from;
head[from]=num;
}
void dfs(int x) {
vis[x]=true;
for(int i=head[x];i!=-1;i=edge[i].next){
int to=edge[i].to;
if(!vis[to]) {
dis[to]=dis[x]+edge[i].w;
dfs(to);
}
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;
memset(head,-1,sizeof(head));
num=0;
m=n-1;
for(int i=1;i<=m;i++){
int x,y;
cin>>x>>y;
addEdge(x,y,1);
addEdge(y,x,1);
}
memset(vis,false,sizeof(vis));
memset(dis,INF,sizeof(dis));
dis[1]=0;
dfs(1);
int maxx=-INF;
for(int i=1;i<=n;i++){
if(dis[i]>maxx&&dis[i]!=INF) {
maxx=dis[i];
start=i;
}
}
memset(vis,false,sizeof(vis));
memset(dis,INF,sizeof(dis));
dis[start]=0;
dfs(start);
maxx=-INF;
for(int i=1;i<=n;i++){
if(dis[i]>maxx&&dis[i]!=INF) {
maxx=dis[i];
endd=i;
}
}
cout<<maxx;
return 0;
}
三、Invitation Cards
题目:In the age of television, not many people attend theater performances. Antique Comedians of Malidinesia are aware of this fact. They want to propagate theater and, most of all, Antique Comedies. They have printed invitation cards with all the necessary information and with the programme. A lot of students were hired to distribute these invitations among the people. Each student volunteer has assigned exactly one bus stop and he or she stays there the whole day and gives invitation to people travelling by bus. A special course was taken where students learned how to influence people and what is the difference between influencing and robbery.
The transport system is very special: all lines are unidirectional and connect exactly two stops. Buses leave the originating stop with passangers each half an hour. After reaching the destination stop they return empty to the originating stop, where they wait until the next full half an hour, e.g. X:00 or X:30, where 'X' denotes the hour. The fee for transport between two stops is given by special tables and is payable on the spot. The lines are planned in such a way, that each round trip (i.e. a journey starting and finishing at the same stop) passes through a Central Checkpoint Stop (CCS) where each passenger has to pass a thorough check including body scan.
All the ACM student members leave the CCS each morning. Each volunteer is to move to one predetermined stop to invite passengers. There are as many volunteers as stops. At the end of the day, all students travel back to CCS. You are to write a computer program that helps ACM to minimize the amount of money to pay every day for the transport of their employees.
思路:利用spfa反向建边,题目给的是双向边,顺着过去和逆着回来各求一次会超时,将箭头反向可以解决
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int inf = 0x3f3f3f3f;
const int M = 1e6+10;
struct Edge
{
int u,v,w;
} e[M];
int v[M],w[M],Next[M],head[M],d[M],edge;
void init(int V)
{
fill(d,d+V,inf);
fill(head,head+V,-1);
edge = 0;
}
void addedge(int a,int b,int x)
{
v[edge]=b;
w[edge]=x;
Next[edge]=head[a];
head[a]=edge++;
}
void SPFA(int s)
{
queue<int> q;
d[s]=0;
q.push(s);
while(!q.empty())
{
int u = q.front();
q.pop();
for(int i=head[u]; i!=-1; i=Next[i])
{
if(d[v[i]]>d[u]+w[i])
{
d[v[i]]=d[u]+w[i];
q.push(v[i]);
}
}
}
}
int main()
{
int n,sum,p,q;
scanf("%d",&n);
while(n--)
{
sum = 0;
scanf("%d%d",&p,&q);
init(p+1);
for(int i = 0; i < q; i++)
{
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
addedge(e[i].u,e[i].v,e[i].w);
}
SPFA(1);
for(int i = 2; i <= p; i++)
{
sum += d[i];
}
init(p+1);
for(int i = 0; i < q; i++)
{
addedge(e[i].v,e[i].u,e[i].w);
}
SPFA(1);
for(int i = 2; i <= p; i++)
{
sum += d[i];
}
printf("%d\n",sum);
}
return 0;
}
四、战略游戏
题目:
他要建立一个古城堡,城堡中的路形成一棵无根树。他要在这棵树的结点上放置最少数目的士兵,使得这些士兵能瞭望到所有的路。
注意,某个士兵在一个结点上时,与该结点相连的所有边将都可以被瞭望到。
请你编一程序,给定一树,帮 Bob 计算出他需要放置最少的士兵
思路:利用树形dp,如果一个节点不放士兵,那么他的子节点就一定要放士兵,可以求出他的状态方程,如果一个节点有放士兵,那么他的子节点状态无关紧要。
#include<bits/stdc++.h>
using namespace std;
const int N=1505;
int n,cur;
int to[N<<1],nex[N<<1],head[N];
int dp[N][2];
void add(int a,int b) {
to[++cur]=b;
nex[cur]=head[a];
head[a]=cur;
}
void read() {
for(int i=1;i<=n;i++) {
int x,k,y; cin>>x>>k;
for(int j=1;j<=k;j++) {
cin>>y;
add(x,y),add(y,x);
}
}
}
void dfs(int u,int fa) {
dp[u][1]=1,dp[u][0]=0;
for(int i=head[u];i;i=nex[i]) {
if(to[i]==fa) continue;
dfs(to[i],u);
dp[u][0]+=dp[to[i]][1];
dp[u][1]+=min(dp[to[i]][1],dp[to[i]][0]);
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n; read(); dfs(0,-1);
cout<<min(dp[0][0],dp[0][1]);
return 0;
}