1007 测试

问题 A: 毛毛虫

时间限制: 1 Sec
内存限制: 128 MB
提交: 16
解决: 13

题目描述

对于一棵树,我们可以将某条链和与该链相连的边抽出来,看上去就象成一个毛毛虫,点数越多,毛毛虫就越大。例如下图左边的树(图 1 )抽出一部分就变成了右边的一个毛毛虫了(图 2 )。

输入

在文本文件 worm.in 中第一行两个整数 N , M ,分别表示树中结点个数和树的边数。

接下来 M 行,每行两个整数 a, b 表示点 a 和点 b 有边连接( a, b ≤ N )。你可以假定没有一对相同的 (a, b) 会出现一次以上。

输出

在文本文件 worm.out 中写入一个整数 , 表示最大的毛毛虫的大小。

样例输入

13 121 21 51 63 24 25 75 87 97 107 118 128 13

样例输出

11

提示

40% 的数据, N ≤ 50000


100% 的数据, N ≤ 300000



问题 B: 十字绣

时间限制: 1 Sec
内存限制: 128 MB
提交: 69
解决: 25

题目描述

 考古学家发现了一块布,布上做有针线活,叫做“十字绣”,即交替地在布的两面穿线。布是一个n*m的网格,线只能在网格的顶点处才能从布的一面穿到另一面。每一段线都覆盖一个单位网格的两条对角线之一,而在绣的过程中,一针中连续的两段线必须分处布的两面。给出布两面的图案,问最少需要几针才能绣出来?一针是指针不离开布的一次绣花过程。

输入

 第1行两个数N和M。

    接下来N行每行M个数描述正面。

    再接下来N行每行M个数描述反面。

每个格子用.(表示空),/(表示从右上角连到左下角),\(表示从左上角连到右下角)和X(表示连两条对角线)表示。

输出

 一个数,最少要用的针数。

样例输入

4 5......\.....\................\.\X.......

样例输出

4

提示


问题 C: 卡农

时间限制: 1 Sec
内存限制: 128 MB
提交: 83
解决: 23

题目描述

 在音乐中,卡农是一种对位的谱曲法 ,它把同一个旋律 以一定的间隔多次重复 。在卡农中,最先出现的旋律是导句 ,以后重复的是答句 。答句必须完全复制导句的节奏和音程,或者其他的一些东西 。所有声音都一模一样的重复的卡农 ,叫做轮唱 。《划船 曲》《两只老虎》都是例子 。

今天我们最熟悉 的卡农作 品是 帕赫贝 尔的《D大调卡农》 ,也称作《帕赫贝尔的卡农》。其曲谱例子如图(1)所示 。

 

Figure 1: 帕赫贝尔的卡农。在曲谱中,第一行(Violin 1)是导句,我们称它为首声部;第二行(Violin 2)是答句,我们称它为二声部;第三行(Violin 3)是另一个答句,我们称它为三声部 。三把小提琴形成三个声部间隔八拍先后加入。小提琴全部拉奏完全相同旋律,音乐悦耳动听。

    柳德米拉也想谱一曲优美的卡农,在聚会的时候不停地演奏。她写了一个旋律,然后尝试把它变成卡农。柳德米拉写的曲子很简单,都是由四分音符构成的(这样每个音的持续的时间都一样,另外一个四分音符的音长就是一拍)。由于她不会转调等比较复杂的技法,她就希望她的音乐的导句和若干答句一模一样,都是她谱写的旋律的不断重复,只不过每个答句形成的声部比前一个进入的声部 (导句或答句)晚若干拍开始。当然,每个答句都要在导句奏完第一遍旋律之前开始。

    柳德米拉发现,虽然她写的旋律很动听,但是将它随意变成一个卡农后,就不是很优美了。她苦思冥想,觉得是这样一个因素作怪 。

如果某个时刻,有两个及以上的音在响,有些音的组合很和谐,而有些就不和谐。柳德米拉发现,如果两个声部,在相同时刻演奏的音高的差,全都是a的倍数,或者全都是b的倍数,那么它们就是优美组合。

 进一步的研究表明,多个声部一起演奏不会显得难听,当且仅当任何两个声部 ,它们都是优美组合。柳德米拉做了一些实验,得到了神奇的数字a和b。现在就请你为她得出她的卡农吧!

 

输入

第一行是测试数据组数t。对于每组数据,第一行是整数n,a,b,代表柳德米拉谱写的旋律的音符数,神奇的数字。接下来一行n个整数h,表示旋律中第i个音符的音高。

输出

 对每组测试数据,输出一行,为她谱出的卡农最多有几个声部。如果不能谱出卡农,输 出0。

样例输入

23 1 11 2 35 2 61 4 7 4 1

样例输出

30

提示

 


【样例解释】



    在第一组数据中,第一个答句在导句演奏完1拍后开始,第二个答句在导句演奏完2拍后开始。可以发现,对于任意两个声部,它们同时演奏的时候,音高差都是1的倍数。又因为每个答句都要在导句奏完第一遍旋律之前开始,所以3就是最大值。 



谱出的曲子表示如下: 



首声部    (导句):    1 2 3 1 2 3. . . 



二声部    (答句):      1 2 3 1 2 3. . . 



三声部    (答句):        1 2 3 1 2 3. . . 



【数据范围及约定】



对于20%的数据,n<=16



对于40%的数据,n<=100



对于60%的数据,n<=1000



对于80%的数据,n<=10^5



有50%的数据,a=b


对于100%的数据,1<=n<=10^6,1<=a,b<=10^9,0<=h[i]<=10^9,0<=t<=3

问题 D: 最小圈

时间限制: 1 Sec
内存限制: 128 MB
提交: 152
解决: 39

题目描述

考虑带圈的有向图G=(V,E)以及w:E→R,每条边e=(i,j)(i<>j,i∈V)的权值定义为w[i,j],令n=|V|。C=(c1,c2,…,ck)(ci∈V)是G中的一个圈当且仅当(c[i],c[i+1])(1<=i<k)和(c[k],c[1])都在E中,这是称k为圈c的长度同时令c[k+1]=c[1],并定义圈c=(c1,c2,…,ck)的平均值为,即c上所有边的权值的平均值。令为G中所有圈c的平均值的最小值。现在的目标是:在给定了一个图G=(V,E)以及w:E→R之后,请求出G中所有圈c的平均值的最小值

输入

第一行包含两个整数n和m,并用一个空格隔开,其中n=|V|,m=|E|分别表示途中有n个点和m条边。接下来m行,每行包含用空格隔开的三个数i,j和w[i,j],表示有一条边(i,j)且该边的权值为w[i,j]。输入数据保证图G=(V,E)连通,存在圈且有一个点能到达其他所有点。

输出

仅包含一个实数 ,要求输出到小数点后8位。

样例输入

4 51 2 52 3 53 1 52 4 34 1 3

样例输出

3.66666667

提示

 【样例说明】 


样例1中共有2个圈(1,2,3)和(1,2,4)。其中第一个圈的平均值为5,第二个圈的平均值为11/3。样例2中存在一个负圈。



【数据范围及约定】



20%的数据:n<=100,m<=1000;



50%的数据:n<=1000,m<=5000;



100%的数据:n<=3000,m<=10000;



100%的数据:|w[i,j]|<=10^7。


T1 毛毛虫 worm

    DFS

首先要搞清楚毛毛虫的定义是啥,我考试的时候愣是没想清楚

毛毛虫就是一条链加上这个链上的点直接连的边

dfs处理出与每一个点相连的最长和次长的链来,

之后加上每个点相连的总边数-1即可(去掉自己)

 

T2 十字绣

DFS+建图

详细的简图题解见波哥给的题解,因为我也是说不明白。

将正图和反图套在一起,之后两边分别建图,dfs即可,最后总针数针+反-再/2

 

T3 卡农

    KMP

需要转化求最小循环节就行

详见波哥题解

 

T4 最小圈

           spfa + 二分答案判定

       我就大致设定一个最小的平均值,之后重新建图权值为w[i][j]-mid

       Spfa判断是否有负环,有的话减小mid

T1

# include <cstdio>
# include <cstring>
# include <vector>

const int MAXN (300010);

int n,m,tot,ans = 0;
int f[MAXN];
int du[MAXN];
int h[MAXN];
bool vis[MAXN];

struct Edge {
	int u,v,next;
} e[MAXN << 1];

void add(int u,int v) {
	e[++tot].u = u;
	e[tot].v = v;
	e[tot].next = h[u];
	h[u] = tot;
}

void dfs(int x) {
	vis[x] = 1;
	if(du[x] == 1) {
		f[x] = 1;
		return ;
	}
	int mx1 = 0,mx2 = 0,cs = 0;
	for(int i = h[x];i;i = e[i].next) {
		if(!vis[e[i].v]) {
			dfs(e[i].v);
			cs++;
			if(f[e[i].v] > mx1) {
				mx2 = mx1;
				mx1 = f[e[i].v];
			}
			else if(f[e[i].v] > mx2) mx2 = f[e[i].v];
		}
	}
	if(ans < mx1 + mx2 + du[x] - 1) ans = mx1 + mx2 + du[x] - 1;
	f[x] = mx1 + cs;
}

void init() {
	int u,v,k;
	scanf("%d%d",&n,&m);
	for(int i = 1; i <= m; ++i) {
		scanf("%d%d",&u,&v);
		add(u,v);
		add(v,u);
		du[u]++;
		du[v]++;
 	}
	for(int i = 1;i <= n;++i) if(du[i] != 1) {
		k = i;
		break;
	}
	dfs(k);
	printf("%d",ans);
}

int main() {
	freopen("worma.in","r",stdin);
	freopen("worma.ans","w",stdout);
	init();
}

T2
# include <cstdio>
# include <cstring>
# include <climits>

using namespace std;

const int MAXN(50005);

int n,m,ans,tot,cs,pos;
char map[205][205];
int w[205][205],h[MAXN],f[MAXN],z[MAXN];
bool zx[MAXN],vis[MAXN];

struct Edge {
	int v,next,w;
} e[MAXN << 3];

int ABS(int x) {
	return x < 0 ? -x : x;
}

void add(int u,int v,int w) {zx[u] = zx[v] = 1;if(w == 1) z[u]++;else f[u]++;e[++tot].v = v;e[tot].next = h[u];h[u] = tot;return ;}

void init() {
	scanf("%d%d",&n,&m);n++;m++;
	for(int i(1); i <= n; ++i) for(int j(1); j <= m; ++j) w[i][j] = ++cs;
	for(int i(1); i < n; ++i) {
		scanf("%s",map[i] + 1);
		for(int j(1); j < m; ++j) {
			if(map[i][j] == (char)92) {
				add(w[i][j],w[i + 1][j + 1],1);add(w[i + 1][j + 1],w[i][j],1);
			} else if(map[i][j] == '/') {
				add(w[i + 1][j],w[i][j + 1],1);add(w[i][j + 1],w[i + 1][j],1);
			} else if(map[i][j] == 'X') {
				add(w[i + 1][j],w[i][j + 1],1);add(w[i][j + 1],w[i + 1][j],1);
				add(w[i][j],w[i + 1][j + 1],1);add(w[i + 1][j + 1],w[i][j],1);
			}
		}
	}
	for(int i(1); i < n; ++i) {
		scanf("%s",map[i] + 1);
		for(int j(1); j < m; ++j) {
			if(map[i][j] == (char)92) {
				add(w[i][j],w[i + 1][j + 1],0);add(w[i + 1][j + 1],w[i][j],0);
			} else if(map[i][j] == '/') {
				add(w[i + 1][j],w[i][j + 1],0);add(w[i][j + 1],w[i + 1][j],0);
			} else if(map[i][j] == 'X') {
				add(w[i + 1][j],w[i][j + 1],0);add(w[i][j + 1],w[i + 1][j],0);
				add(w[i][j],w[i + 1][j + 1],0);add(w[i + 1][j + 1],w[i][j],0);
			}
		}
	}	
}

void dfs(int x) {
	vis[x] = 1;pos += ABS(z[x] - f[x]);
	for(int i = h[x];i;i = e[i].next) {if(vis[e[i].v]) continue;dfs(e[i].v);}
}

void make(){
	for(int i(1);i <= cs;++i) {
		if(!vis[i] && zx[i]) {
			pos = 0;dfs(i);
			if(!pos) ans+=2;
			else ans += pos; 
		}
	}
	printf("%d",ans / 2);
}

int main() {
	freopen("stitch.in","r",stdin);
	freopen("stitch.out","w",stdout);
	init();
	make();
	return 0;
}
T3
# include <cstdio>
# include <cstring>
# include <string>

using namespace std;

const int MAXN = 1000010;

int T;
int a,b,n;
int song[MAXN];
int nxt[MAXN];
int temp[MAXN];

int getnxt(int x) {
	memset(nxt,0,sizeof(nxt));
	for(int i = 0; i < n; ++i) temp[i] = song[i];
	for(int i = 0; i < n; ++i) temp[i] %= x;
	nxt[0] = 0;
	for(int i = 1; i <n; ++i) {
		int k = nxt[i];
		while(k && temp[k ] != temp[i]) k = nxt[k];
		if(temp[k ] == temp[i]) nxt[i+1] = k + 1;
	}
	/*for(int i = 1;i <= n;++i) printf("%d ",nxt[i]);
	printf("\n"); */
	return n - nxt[n];
}

void init() {
	scanf("%d%d%d",&n,&a,&b);
	for(int i = 0; i < n; ++i) scanf("%d",&song[i]);
	if(a == b) {
		int ans1 = getnxt(a);
		if(n % ans1 == 0 && ans1 != n) {
			printf("%d\n",n / ans1);
		} else {
			printf("0\n");
		}
	} else {
		int ans1 = getnxt(a);
		int ans2 = getnxt(b);
		if(n % ans1 == 0 && n != ans1) {
			ans1 = n / ans1;
		}
		else {
			ans1 = 0;
		}
		if(n % ans2 == 0 && n != ans2) {
			ans2 = n / ans2;
		}
		else {
			ans2 = 0;
		}
		if(ans1 > ans2) {
			printf("%d\n",ans1);
		}
		else {
			printf("%d\n",ans2);
		}
	}
}

void clr() {
	memset(song,0,sizeof(song));
	memset(nxt,0,sizeof(nxt));
}

int main() {
	freopen("canon.in","r",stdin);
	freopen("canon.out","w",stdout);
	scanf("%d",&T);
	while(T--) {
		init();
		clr();
	}
}
T4
# include <cstdio>
# include <cstring>

using namespace std;

const int MAXN(3010);
const int MAXM(10010);
const double eps(1e-9);

bool flag;
bool mark[MAXN];
int n,m,tot;
int h[MAXM];
int u[MAXM];
int v[MAXM];
double w[MAXM];
double dis[MAXM];
double l,r,mid;

struct Edge {
	int u,v,next;
	double w;
} e[MAXM << 1];

void add(int u,int v,double w) {
	e[++tot].u = u;
	e[tot].v = v;
	e[tot].w = w;
	e[tot].next = h[u];
	h[u] = tot;
	return ;
}

void init() {
	scanf("%d%d",&n,&m);
	for(int i = 1; i <= m; ++i) scanf("%d%d%lf",&u[i],&v[i],&w[i]),r += w[i];
	return ;
}

void dfs(int x) {
	mark[x] = 1;
	for(int i = h[x]; i; i = e[i].next) {
		if(dis[e[i].v] > dis[x] + e[i].w) {
			if(mark[e[i].v]) {
				flag = 1;
				break;
			} else {
				dis[e[i].v] = dis[x] + e[i].w;
				dfs(e[i].v);
			}
		}
	}
	mark[x] = 0;
}

bool check(double x) {
	for(int i = 1; i <= n; ++i) {
		dfs(i);
		if(flag) return 1;
	}
	return 0;
}

void build(double x) {
	memset(h,0,sizeof(h));
	tot = 0;
	for(int i = 1; i <= m; ++i) add(u[i],v[i],w[i] - x);
}

void clr() {
	build(mid);
	flag = 0;
	for(int i = 0; i <= n; ++i) dis[i] = 0.0;
	return ;
}

void divide() {
	while(r - l >= eps) {
		mid = (l + r) / 2.0;
		clr();
		if(check(mid)) r = mid;
		else l = mid;
	}
	printf("%.8lf",l);
	return ;
}

int main() {
	freopen("cycle.in","r",stdin);
	freopen("cycle.out","w",stdout);
	init();
	divide();
	return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值