http://poj.org/problem?id=1789
这是一道图论的题,个人觉得和那个POJ1258是差不多的,就是多了一步,题目难以读懂
题目的意思:就是给你一群字符串要你找字符串对应的字符不同,使得这个字符串与其他字符串不同
举个例子,不然题目也确实看不懂,
4
a b a a a b a
b a a a a b a
b a a b b a b
a b a a a a a
以第一个为主的与其他行不同的字母数分别为:0 2 6 1
以第二个为主的与其他行不同的字母数分别为:2 0 4 3
以第三个为主的与其他行不同的字母数分别为:6 4 0 5
以第四个为主的与其他行不同的字母数分别为:1 3 5 0
所求的最短的不是2+6+1=9;
而应该是 1+2+4,这才是最短的,这就是prim。
而所谓的prim,就是首先以一个节点作为最小生成树的初始节点,然后以迭代的方式找出与最小生成树中各节点权重最小的边。
用代码来解释是比较好的。
1 #include <stdio.h> 2 #include <iostream> 3 #include <string.h> 4 #include <string> 5 6 using namespace std; 7 8 #define inf 100007 9 char str[2005][7]; 10 int dis[2005],n,ans,mp[2004][2004]; 11 bool vis[2005]; 12 void creatmp() 13 { 14 for(int i=1;i<=n;i++) 15 for(int j=1;j<=n;j++) 16 { 17 ans=0; 18 for(int k=0;k<7;k++) 19 if(str[i][k]!=str[j][k]) ans++; 20 mp[i][j]=ans; 21 } 22 } 23 24 bool prim() 25 { 26 ans=0; 27 for(int i=1;i<=n;i++) //对dis进行初始化,这里的dis指的就是两个字符串对应位置的字符的不同总值。 28 dis[i]=inf; 29 dis[1]=0; //因为相同字符串是相同的,所以这个为0。 30 for(int i=1;i<=n;i++) 31 { 32 int tmp=inf;int k=0; 33 for(int j=1;j<=n;j++) 34 if(vis[j]&&dis[j]<tmp) //找出dis最小的,并记录。 35 { 36 tmp=dis[j]; 37 k=j; 38 } 39 if(tmp==inf) return false; 40 ans+=tmp; 41 vis[k]=false; 42 for(int j=1;j<=n;j++) //用dis来记录每一列。 43 if(vis[j]&&dis[j]>mp[k][j]) 44 dis[j]=mp[k][j]; 45 } 46 return true; 47 } 48 49 int main() 50 { 51 while(scanf("%d",&n)&&n!=0) 52 { 53 memset(vis,true,sizeof(vis)); 54 for(int i=1;i<=n;i++) 55 scanf("%s",str[i]); 56 creatmp(); 57 for(int i=1;i<=n;i++){ 58 for(int j=1;j<=n;j++) 59 printf("%d ",mp[i][j]); 60 printf(" ");} 61 prim(); 62 printf("The highest possible quality is 1/%d. ",ans); 63 } 64 }