1 import java.io.*;
  2 import java.util.*;
  3 /*
  4 ID: yanglei4
  5 LANG: JAVA
  6 TASK:fence6
  7 */
  8 public class fence6 {
  9     public static void main(String[] args) throws IOException {
 10         BufferedReader f = new BufferedReader(new FileReader("fence6.in"));
 11         PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("fence6.out")));
 12         int N = Integer.parseInt(f.readLine());
 13         int[][] D = new int[N * 2][N * 2];
 14         //init D
 15         for (int i = 0; i < N * 2; i++)
 16             for (int j = 0; j < N * 2; j++)
 17                 D[i][j] = -1;
 18         
 19         int PointCount = 0;
 20         int[][] PointsDesc = new int[2 * N][N + 1];
 21         int[][] LineDesc = new int[N + 1][2];
 22         
 23         //input and create the matrix
 24         for (int i = 0; i < N; i++) {
 25             StringTokenizer st = new StringTokenizer(f.readLine());
 26             int LineNumber = Integer.parseInt(st.nextToken());
 27             int LineLength = Integer.parseInt(st.nextToken());
 28             int LeftCount = Integer.parseInt(st.nextToken());
 29             int RightCount = Integer.parseInt(st.nextToken());
 30             
 31             int[] LeftPoints = new int[LeftCount];
 32             int[] RightPoints = new int[RightCount];
 33             
 34             //Read the Left Points
 35             st = new StringTokenizer(f.readLine());
 36             for (int j = 0; j < LeftCount; j++)
 37                 LeftPoints[j] = Integer.parseInt(st.nextToken());
 38 
 39             //Read the Right Pints
 40             st = new StringTokenizer(f.readLine());
 41             for (int j = 0; j < RightCount; j++)
 42                 RightPoints[j] = Integer.parseInt(st.nextToken());
 43             
 44             int firstpoint = -1;
 45             int secondpoint = -1;
 46             
 47             //Find if their connection points exist
 48             for (int j = 0; j < PointCount; j++) {
 49                 if (PointsDesc[j][LineNumber] == 1)
 50                 {
 51                     boolean flag = true;
 52                     for (int k = 0; k < LeftCount; k++
 53                         if (PointsDesc[j][LeftPoints[k]] == 0) {
 54                             flag = false;
 55                             break;
 56                         }
 57                     if (flag) 
 58                         firstpoint = j;
 59                 }
 60                 
 61                 
 62                 if (PointsDesc[j][LineNumber] == 1) {
 63                     boolean flag = true;
 64                     for (int k = 0; k < RightCount; k++
 65                         if (PointsDesc[j][RightPoints[k]] == 0) {
 66                             flag = false;
 67                             break;
 68                         }                
 69                     if (flag) 
 70                         secondpoint = j;
 71                 }
 72             }
 73                 
 74             if (firstpoint == -1)
 75             {    
 76                 PointsDesc[PointCount][LineNumber] = 1;
 77                 for (int k = 0; k < LeftCount; k++)
 78                     PointsDesc[PointCount][LeftPoints[k]] = 1;
 79                 firstpoint = PointCount;
 80                 PointCount++;
 81             }
 82             if (secondpoint == -1)
 83             {
 84                 PointsDesc[PointCount][LineNumber] = 1;                
 85                 for (int k = 0; k < RightCount; k++)
 86                     PointsDesc[PointCount][RightPoints[k]] = 1;
 87                 secondpoint = PointCount;
 88                 PointCount++;
 89             }
 90             
 91             D[firstpoint][secondpoint] = LineLength;
 92             D[secondpoint][firstpoint] = LineLength;
 93             LineDesc[LineNumber][0= firstpoint;
 94             LineDesc[LineNumber][1= secondpoint;
 95         }
 96         
 97 /*        System.out.print("   ");
 98         for (int i = 0; i < PointCount; i++) System.out.print(i + "\t");
 99             System.out.println();
100         
101         for (int i = 0; i < PointCount; i++) {
102             System.out.print(i + ": ");
103             for (int j = 0; j < PointCount; j++)
104                 System.out.print(D[i][j] + "\t");
105             System.out.println();                
106         }*/
107         
108 /*        for (int i = 0; i < PointCount; i++) {
109             System.out.print("a" + i + ": ");
110             for (int j = 1; j <= N; j++)
111                 if (PointsDesc[i][j]!=0) 
112                     System.out.print(j + " ");
113             System.out.println();
114         }*/
115         
116         int min = 1000000;
117         for (int l = 1; l <= N; l++)
118         {
119             int left = LineDesc[l][0];
120             int right = LineDesc[l][1];
121             int temp = D[left][right];
122             //System.out.print(left + "," + right + "\t");
123             D[left][right] = -1;
124             D[right][left] = -1;
125 
126             int source = left;
127             
128             int[] distance = new int[PointCount];
129             for (int i = 0; i < PointCount; i++
130                 if (D[source][i] != - 1)
131                     distance[i] = D[source][i];
132                 else
133                     distance[i] = 1000000;
134             
135             boolean[] visited = new boolean[PointCount];
136             int nodevisited = 1;
137             distance[source] = 0;
138             visited[source] = true;
139             while (nodevisited < PointCount) {
140                 int mindis = 1000000;
141                 int find = -1;
142                 for (int k = 0; k < PointCount; k++)
143                     if (visited[k] == false && k != source && distance[k] < mindis)
144                         {
145                             mindis = distance[k];
146                             find = k;
147                         }
148                 if (find != -1) {
149                     visited[find] = true;
150                     distance[find] = mindis;
151                     for (int k = 0; k < PointCount; k++)
152                         if (D[find][k] != -1) {
153                             if (distance[find] + D[find][k] < distance[k])
154                                 distance[k] = distance[find] + D[find][k];
155                         }    
156                 }
157                 nodevisited++;
158             }
159 /*            for (int i = 0; i < PointCount; i++) System.out.print(distance[i] + " ");
160             System.out.println();*/
161             if (distance[right] + temp < min)
162                 min = distance[right] + temp;
163             
164             D[left][right] = temp;
165             D[right][left]= temp;
166         }
167         out.println(min);
168         out.close();
169         System.exit(0);
170     }
171 }
172 

可惜BlogJava的着色不是很好看

USACO 4.1.1 Fence Loops
说一下大致的做法吧,算是结题报告,不过可能会被鄙视。
首先就是把图转化一下,因为题里面给的那种表达形式是没办法用任何关于点的图的算法的。
我的转化方法就是:
对于每条边,最多在图中添加两个新的节点,这要取决于该节点是否与图中的其他节点重合
打个比方来说,例子中的边2,当你添加这条边的时候,你就只需要添加一个新的节点,因为这条变的一个节点跟边1的一个节点重合了。
现在的问题就是,怎么来判断要添加的节点跟现有的节点是否重合。
我们可以发现,如果两个节点,他们所共有的边是一样的,那么这两个节点肯定就是一个点。
比如,例子中的左上角第一个点,它的占有的边的集合是(1,2,7)
当你在处理边2的时候,你会发现,它有一个端点链接的边是(1,7),算上它自己,就也是(1,2,7)
于是,他们肯定是共享一个点的。
不知道说清楚了没有
通过这个过程,就可以把输入的图转化成为一个邻接矩阵。
后来的算法我是看了NOCOW才知道的,刚开始想用Floyd直接算到自己的回路,发现不行,因为一条边可能被用两次。那样就不是一个封闭的图形了。
NOCOW上的办法就是,一次去掉一个边,然后算这条边两边节点的最短路
如果存在的话,结果再加上这条边的长度,那么就是这个封闭图的周长。
总共算N次,由于途中的节点最多最多也只能有N + 1个,就是一个接着一个,连成一个环的情况。
所以算法的复杂度应该是O(N^3),还不是很坏。
我没做什么剪枝,用JAVA写的,也直接过了。
中间Dij算法写错了N次,现在想想,以前写的可能也得是错的,但是都没有被找出毛病来。